Merge pull request #18518 from amcasey/ExtractMethodFixes25

Port Extract Method fixes from master
This commit is contained in:
Andrew Casey
2017-09-20 10:58:17 -07:00
committed by GitHub
44 changed files with 792 additions and 1099 deletions
+2
View File
@@ -2596,4 +2596,6 @@ namespace ts {
export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) {
return sourceFile.checkJsDirective ? sourceFile.checkJsDirective.enabled : compilerOptions.checkJs;
}
export function assertTypeIsNever(_: never): void {}
}
+164 -5
View File
@@ -378,7 +378,37 @@ namespace A {
"Cannot extract range containing conditional return statement."
]);
testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, ["Select more than a single token."]);
testExtractRangeFailed("extractRangeFailed7",
`
function test(x: number) {
while (x) {
x--;
[#|break;|]
}
}
`,
[
"Cannot extract range containing conditional break or continue statements."
]);
testExtractRangeFailed("extractRangeFailed8",
`
function test(x: number) {
switch (x) {
case 1:
[#|break;|]
}
}
`,
[
"Cannot extract range containing conditional break or continue statements."
]);
testExtractRangeFailed("extract-method-not-for-token-expression-statement", `[#|a|]`, ["Select more than a single identifier."]);
testExtractRangeFailed("extractRangeFailed9",
`var x = ([#||]1 + 2);`,
[
"Statement or expression expected."
]);
testExtractMethod("extractMethod1",
`namespace A {
@@ -547,12 +577,141 @@ namespace A {
}
}
}`);
testExtractMethod("extractMethod20",
`const _ = class {
a() {
[#|let a1 = { x: 1 };
return a1.x + 10;|]
}
}`);
// Write + void return
testExtractMethod("extractMethod21",
`function foo() {
let x = 10;
[#|x++;
return;|]
}`);
// Return in finally block
testExtractMethod("extractMethod22",
`function test() {
try {
}
finally {
[#|return 1;|]
}
}`);
// Extraction position - namespace
testExtractMethod("extractMethod23",
`namespace NS {
function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }
}`);
// Extraction position - function
testExtractMethod("extractMethod24",
`function Outer() {
function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }
}`);
// Extraction position - file
testExtractMethod("extractMethod25",
`function M1() { }
function M2() {
[#|return 1;|]
}
function M3() { }`);
// Extraction position - class without ctor
testExtractMethod("extractMethod26",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
M3() { }
}`);
// Extraction position - class with ctor in middle
testExtractMethod("extractMethod27",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
constructor() { }
M3() { }
}`);
// Extraction position - class with ctor at end
testExtractMethod("extractMethod28",
`class C {
M1() { }
M2() {
[#|return 1;|]
}
M3() { }
constructor() { }
}`);
// Shorthand property names
testExtractMethod("extractMethod29",
`interface UnaryExpression {
kind: "Unary";
operator: string;
operand: any;
}
function parseUnaryExpression(operator: string): UnaryExpression {
[#|return {
kind: "Unary",
operator,
operand: parsePrimaryExpression(),
};|]
}
function parsePrimaryExpression(): any {
throw "Not implemented";
}`);
// Return in nested function
testExtractMethod("extractMethod31",
`namespace N {
export const value = 1;
() => {
var f: () => number;
[#|f = function (): number {
return value;
}|]
}
}`);
// Return in nested class
testExtractMethod("extractMethod32",
`namespace N {
export const value = 1;
() => {
[#|var c = class {
M() {
return value;
}
}|]
}
}`);
// Selection excludes leading trivia of declaration
testExtractMethod("extractMethod33",
`function F() {
[#|function G() { }|]
}`);
});
function testExtractMethod(caption: string, text: string) {
it(caption, () => {
Harness.Baseline.runBaseline(`extractMethod/${caption}.js`, () => {
Harness.Baseline.runBaseline(`extractMethod/${caption}.ts`, () => {
const t = extractTest(text);
const selectionRange = t.ranges.get("selection");
if (!selectionRange) {
@@ -562,7 +721,7 @@ namespace A {
path: "/a.ts",
content: t.source
};
const host = projectSystem.createServerHost([f]);
const host = projectSystem.createServerHost([f, projectSystem.libFile]);
const projectService = projectSystem.createProjectService(host);
projectService.openClientFile(f.path);
const program = projectService.inferredProjects[0].getLanguageService().getProgram();
@@ -579,12 +738,12 @@ namespace A {
assert.equal(result.errors, undefined, "expect no errors");
const results = refactor.extractMethod.getPossibleExtractions(result.targetRange, context);
const data: string[] = [];
data.push(`==ORIGINAL==`);
data.push(`// ==ORIGINAL==`);
data.push(sourceFile.text);
for (const r of results) {
const { renameLocation, edits } = refactor.extractMethod.getExtractionAtIndex(result.targetRange, context, results.indexOf(r));
assert.lengthOf(edits, 1);
data.push(`==SCOPE::${r.scopeDescription}==`);
data.push(`// ==SCOPE::${r.scopeDescription}==`);
const newText = textChanges.applyChanges(sourceFile.text, edits[0].textChanges);
const newTextWithRename = newText.slice(0, renameLocation) + "/*RENAME*/" + newText.slice(renameLocation);
data.push(newTextWithRename);
+93 -49
View File
@@ -92,7 +92,7 @@ namespace ts.refactor.extractMethod {
export const CannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators: DiagnosticMessage = createMessage("Cannot extract range containing writes to references located outside of the target range in generators.");
export const TypeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope.");
export const FunctionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope.");
export const InsufficientSelection = createMessage("Select more than a single token.");
export const InsufficientSelection = createMessage("Select more than a single identifier.");
export const CannotExtractExportedEntity = createMessage("Cannot extract exported declaration");
export const CannotCombineWritesAndReturns = createMessage("Cannot combine writes and returns");
export const CannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor");
@@ -149,6 +149,11 @@ namespace ts.refactor.extractMethod {
// exported only for tests
export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan): RangeToExtract {
const length = span.length || 0;
if (length === 0) {
return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.StatementOrExpressionExpected)] };
}
// Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span.
// This may fail (e.g. you select two statements in the root of a source file)
let start = getParentNodeInSpan(getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false), sourceFile, span);
@@ -227,7 +232,7 @@ namespace ts.refactor.extractMethod {
}
function checkRootNode(node: Node): Diagnostic[] | undefined {
if (isToken(isExpressionStatement(node) ? node.expression : node)) {
if (isIdentifier(isExpressionStatement(node) ? node.expression : node)) {
return [createDiagnosticForNode(node, Messages.InsufficientSelection)];
}
return undefined;
@@ -340,45 +345,31 @@ namespace ts.refactor.extractMethod {
return false;
}
const savedPermittedJumps = permittedJumps;
if (node.parent) {
switch (node.parent.kind) {
case SyntaxKind.IfStatement:
if ((<IfStatement>node.parent).thenStatement === node || (<IfStatement>node.parent).elseStatement === node) {
// forbid all jumps inside thenStatement or elseStatement
permittedJumps = PermittedJumps.None;
}
break;
case SyntaxKind.TryStatement:
if ((<TryStatement>node.parent).tryBlock === node) {
// forbid all jumps inside try blocks
permittedJumps = PermittedJumps.None;
}
else if ((<TryStatement>node.parent).finallyBlock === node) {
// allow unconditional returns from finally blocks
permittedJumps = PermittedJumps.Return;
}
break;
case SyntaxKind.CatchClause:
if ((<CatchClause>node.parent).block === node) {
// forbid all jumps inside the block of catch clause
permittedJumps = PermittedJumps.None;
}
break;
case SyntaxKind.CaseClause:
if ((<CaseClause>node).expression !== node) {
// allow unlabeled break inside case clauses
permittedJumps |= PermittedJumps.Break;
}
break;
default:
if (isIterationStatement(node.parent, /*lookInLabeledStatements*/ false)) {
if ((<IterationStatement>node.parent).statement === node) {
// allow unlabeled break/continue inside loops
permittedJumps |= PermittedJumps.Break | PermittedJumps.Continue;
}
}
break;
}
switch (node.kind) {
case SyntaxKind.IfStatement:
permittedJumps = PermittedJumps.None;
break;
case SyntaxKind.TryStatement:
// forbid all jumps inside try blocks
permittedJumps = PermittedJumps.None;
break;
case SyntaxKind.Block:
if (node.parent && node.parent.kind === SyntaxKind.TryStatement && (<TryStatement>node).finallyBlock === node) {
// allow unconditional returns from finally blocks
permittedJumps = PermittedJumps.Return;
}
break;
case SyntaxKind.CaseClause:
// allow unlabeled break inside case clauses
permittedJumps |= PermittedJumps.Break;
break;
default:
if (isIterationStatement(node, /*lookInLabeledStatements*/ false)) {
// allow unlabeled break/continue inside loops
permittedJumps |= PermittedJumps.Break | PermittedJumps.Continue;
}
break;
}
switch (node.kind) {
@@ -405,7 +396,7 @@ namespace ts.refactor.extractMethod {
}
}
else {
if (!(permittedJumps & (SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) {
if (!(permittedJumps & (node.kind === SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) {
// attempt to break or continue in a forbidden context
(errors || (errors = [])).push(createDiagnosticForNode(node, Messages.CannotExtractRangeContainingConditionalBreakOrContinueStatements));
}
@@ -570,7 +561,7 @@ namespace ts.refactor.extractMethod {
else if (isClassLike(scope)) {
return scope.kind === SyntaxKind.ClassDeclaration
? `class '${scope.name.text}'`
: scope.name.text
: scope.name && scope.name.text
? `class expression '${scope.name.text}'`
: "anonymous class expression";
}
@@ -683,8 +674,14 @@ namespace ts.refactor.extractMethod {
}
const changeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
// insert function at the end of the scope
changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter });
const minInsertionPos = (isReadonlyArray(range.range) ? lastOrUndefined(range.range) : range.range).end;
const nodeToInsertBefore = getNodeToInsertBefore(minInsertionPos, scope);
if (nodeToInsertBefore) {
changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, { suffix: context.newLineCharacter + context.newLineCharacter });
}
else {
changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter });
}
const newNodes: Node[] = [];
// replace range with function call
@@ -722,6 +719,10 @@ namespace ts.refactor.extractMethod {
}
else {
newNodes.push(createStatement(createBinary(assignments[0].name, SyntaxKind.EqualsToken, call)));
if (range.facts & RangeFacts.HasReturn) {
newNodes.push(createReturn());
}
}
}
else {
@@ -762,6 +763,39 @@ namespace ts.refactor.extractMethod {
const renameFilename = renameRange.getSourceFile().fileName;
const renameLocation = getRenameLocation(edits, renameFilename, functionNameText);
return { renameFilename, renameLocation, edits };
function getStatementsOrClassElements(scope: Scope): ReadonlyArray<Statement> | ReadonlyArray<ClassElement> {
if (isFunctionLike(scope)) {
const body = scope.body;
if (isBlock(body)) {
return body.statements;
}
}
else if (isModuleBlock(scope) || isSourceFile(scope)) {
return scope.statements;
}
else if (isClassLike(scope)) {
return scope.members;
}
else {
assertTypeIsNever(scope);
}
return emptyArray;
}
/**
* If `scope` contains a function after `minPos`, then return the first such function.
* Otherwise, return `undefined`.
*/
function getNodeToInsertBefore(minPos: number, scope: Scope): Node | undefined {
const children = getStatementsOrClassElements(scope);
for (const child of children) {
if (child.pos >= minPos && isFunctionLike(child) && !isConstructorDeclaration(child)) {
return child;
}
}
}
}
function getRenameLocation(edits: ReadonlyArray<FileTextChanges>, renameFilename: string, functionNameText: string): number {
@@ -794,12 +828,14 @@ namespace ts.refactor.extractMethod {
}
}
function transformFunctionBody(body: Node, writes: ReadonlyArray<UsageEntry>, substitutions: ReadonlyMap<Node>, hasReturn: boolean): { body: Block, returnValueProperty: string } {
if (isBlock(body) && !writes && substitutions.size === 0) {
// already block, no writes to propagate back, no substitutions - can use node as is
return { body: createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
}
let returnValueProperty: string;
let ignoreReturns = false;
const statements = createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : createReturn(<Expression>body)]);
// rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
if (writes || substitutions.size) {
@@ -822,7 +858,7 @@ namespace ts.refactor.extractMethod {
}
function visitor(node: Node): VisitResult<Node> {
if (node.kind === SyntaxKind.ReturnStatement && writes) {
if (!ignoreReturns && node.kind === SyntaxKind.ReturnStatement && writes) {
const assignments: ObjectLiteralElementLike[] = getPropertyAssignmentsForWrites(writes);
if ((<ReturnStatement>node).expression) {
if (!returnValueProperty) {
@@ -838,8 +874,12 @@ namespace ts.refactor.extractMethod {
}
}
else {
const oldIgnoreReturns = ignoreReturns;
ignoreReturns = ignoreReturns || isFunctionLike(node) || isClassLike(node);
const substitution = substitutions.get(getNodeId(node).toString());
return substitution || visitEachChild(node, visitor, nullTransformationContext);
const result = substitution || visitEachChild(node, visitor, nullTransformationContext);
ignoreReturns = oldIgnoreReturns;
return result;
}
}
}
@@ -992,7 +1032,11 @@ namespace ts.refactor.extractMethod {
}
function recordUsagebySymbol(identifier: Identifier, usage: Usage, isTypeName: boolean) {
const symbol = checker.getSymbolAtLocation(identifier);
// If the identifier is both a property name and its value, we're only interested in its value
// (since the name is a declaration and will be included in the extracted range).
const symbol = identifier.parent && isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier
? checker.getShorthandAssignmentValueSymbol(identifier.parent)
: checker.getSymbolAtLocation(identifier);
if (!symbol) {
// cannot find symbol - do nothing
return undefined;
@@ -1026,7 +1070,7 @@ namespace ts.refactor.extractMethod {
if (!declInFile) {
return undefined;
}
if (rangeContainsRange(enclosingTextRange, declInFile)) {
if (rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) {
// declaration is located in range to be extracted - do nothing
return undefined;
}
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
let x = 1;
function foo() {
@@ -14,7 +14,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
let x = 1;
function foo() {
@@ -34,7 +34,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
let x = 1;
function foo() {
@@ -55,7 +55,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
let x = 1;
function foo() {
@@ -76,7 +76,7 @@ namespace A {
return a;
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
let x = 1;
function foo() {
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
export interface I { x: number };
class C {
@@ -9,7 +9,7 @@ namespace A {
}
}
}
==SCOPE::class 'C'==
// ==SCOPE::class 'C'==
namespace A {
export interface I { x: number };
class C {
@@ -24,7 +24,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
export interface I { x: number };
class C {
@@ -39,7 +39,7 @@ namespace A {
return a1.x + 10;
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
export interface I { x: number };
class C {
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
let y = 1;
class C {
@@ -11,7 +11,7 @@ namespace A {
}
}
}
==SCOPE::class 'C'==
// ==SCOPE::class 'C'==
namespace A {
let y = 1;
class C {
@@ -30,7 +30,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
let y = 1;
class C {
@@ -49,7 +49,7 @@ namespace A {
return { __return: a1.x + 10, z };
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
let y = 1;
class C {
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
let y = 1;
class C {
@@ -13,7 +13,7 @@ namespace A {
}
}
}
==SCOPE::class 'C'==
// ==SCOPE::class 'C'==
namespace A {
let y = 1;
class C {
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
let x = 1;
function foo() {
@@ -12,7 +12,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
let x = 1;
function foo() {
@@ -30,7 +30,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
let x = 1;
function foo() {
@@ -48,7 +48,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
let x = 1;
function foo() {
@@ -66,7 +66,7 @@ namespace A {
return foo();
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
let x = 1;
function foo() {
@@ -0,0 +1,28 @@
// ==ORIGINAL==
const _ = class {
a() {
let a1 = { x: 1 };
return a1.x + 10;
}
}
// ==SCOPE::anonymous class expression==
const _ = class {
a() {
return this./*RENAME*/newFunction();
}
private newFunction() {
let a1 = { x: 1 };
return a1.x + 10;
}
}
// ==SCOPE::global scope==
const _ = class {
a() {
return /*RENAME*/newFunction();
}
}
function newFunction() {
let a1 = { x: 1 };
return a1.x + 10;
}
@@ -0,0 +1,26 @@
// ==ORIGINAL==
function foo() {
let x = 10;
x++;
return;
}
// ==SCOPE::function 'foo'==
function foo() {
let x = 10;
return /*RENAME*/newFunction();
function newFunction() {
x++;
return;
}
}
// ==SCOPE::global scope==
function foo() {
let x = 10;
x = /*RENAME*/newFunction(x);
return;
}
function newFunction(x: number) {
x++;
return x;
}
@@ -0,0 +1,31 @@
// ==ORIGINAL==
function test() {
try {
}
finally {
return 1;
}
}
// ==SCOPE::function 'test'==
function test() {
try {
}
finally {
return /*RENAME*/newFunction();
}
function newFunction() {
return 1;
}
}
// ==SCOPE::global scope==
function test() {
try {
}
finally {
return /*RENAME*/newFunction();
}
}
function newFunction() {
return 1;
}
@@ -0,0 +1,43 @@
// ==ORIGINAL==
namespace NS {
function M1() { }
function M2() {
return 1;
}
function M3() { }
}
// ==SCOPE::function 'M2'==
namespace NS {
function M1() { }
function M2() {
return /*RENAME*/newFunction();
function newFunction() {
return 1;
}
}
function M3() { }
}
// ==SCOPE::namespace 'NS'==
namespace NS {
function M1() { }
function M2() {
return /*RENAME*/newFunction();
}
function newFunction() {
return 1;
}
function M3() { }
}
// ==SCOPE::global scope==
namespace NS {
function M1() { }
function M2() {
return /*RENAME*/newFunction();
}
function M3() { }
}
function newFunction() {
return 1;
}
@@ -0,0 +1,43 @@
// ==ORIGINAL==
function Outer() {
function M1() { }
function M2() {
return 1;
}
function M3() { }
}
// ==SCOPE::function 'M2'==
function Outer() {
function M1() { }
function M2() {
return /*RENAME*/newFunction();
function newFunction() {
return 1;
}
}
function M3() { }
}
// ==SCOPE::function 'Outer'==
function Outer() {
function M1() { }
function M2() {
return /*RENAME*/newFunction();
}
function newFunction() {
return 1;
}
function M3() { }
}
// ==SCOPE::global scope==
function Outer() {
function M1() { }
function M2() {
return /*RENAME*/newFunction();
}
function M3() { }
}
function newFunction() {
return 1;
}
@@ -0,0 +1,26 @@
// ==ORIGINAL==
function M1() { }
function M2() {
return 1;
}
function M3() { }
// ==SCOPE::function 'M2'==
function M1() { }
function M2() {
return /*RENAME*/newFunction();
function newFunction() {
return 1;
}
}
function M3() { }
// ==SCOPE::global scope==
function M1() { }
function M2() {
return /*RENAME*/newFunction();
}
function newFunction() {
return 1;
}
function M3() { }
@@ -0,0 +1,31 @@
// ==ORIGINAL==
class C {
M1() { }
M2() {
return 1;
}
M3() { }
}
// ==SCOPE::class 'C'==
class C {
M1() { }
M2() {
return this./*RENAME*/newFunction();
}
private newFunction() {
return 1;
}
M3() { }
}
// ==SCOPE::global scope==
class C {
M1() { }
M2() {
return /*RENAME*/newFunction();
}
M3() { }
}
function newFunction() {
return 1;
}
@@ -0,0 +1,34 @@
// ==ORIGINAL==
class C {
M1() { }
M2() {
return 1;
}
constructor() { }
M3() { }
}
// ==SCOPE::class 'C'==
class C {
M1() { }
M2() {
return this./*RENAME*/newFunction();
}
constructor() { }
private newFunction() {
return 1;
}
M3() { }
}
// ==SCOPE::global scope==
class C {
M1() { }
M2() {
return /*RENAME*/newFunction();
}
constructor() { }
M3() { }
}
function newFunction() {
return 1;
}
@@ -0,0 +1,34 @@
// ==ORIGINAL==
class C {
M1() { }
M2() {
return 1;
}
M3() { }
constructor() { }
}
// ==SCOPE::class 'C'==
class C {
M1() { }
M2() {
return this./*RENAME*/newFunction();
}
private newFunction() {
return 1;
}
M3() { }
constructor() { }
}
// ==SCOPE::global scope==
class C {
M1() { }
M2() {
return /*RENAME*/newFunction();
}
M3() { }
constructor() { }
}
function newFunction() {
return 1;
}
@@ -0,0 +1,62 @@
// ==ORIGINAL==
interface UnaryExpression {
kind: "Unary";
operator: string;
operand: any;
}
function parseUnaryExpression(operator: string): UnaryExpression {
return {
kind: "Unary",
operator,
operand: parsePrimaryExpression(),
};
}
function parsePrimaryExpression(): any {
throw "Not implemented";
}
// ==SCOPE::function 'parseUnaryExpression'==
interface UnaryExpression {
kind: "Unary";
operator: string;
operand: any;
}
function parseUnaryExpression(operator: string): UnaryExpression {
return /*RENAME*/newFunction();
function newFunction() {
return {
kind: "Unary",
operator,
operand: parsePrimaryExpression(),
};
}
}
function parsePrimaryExpression(): any {
throw "Not implemented";
}
// ==SCOPE::global scope==
interface UnaryExpression {
kind: "Unary";
operator: string;
operand: any;
}
function parseUnaryExpression(operator: string): UnaryExpression {
return /*RENAME*/newFunction(operator);
}
function newFunction(operator: string) {
return {
kind: "Unary",
operator,
operand: parsePrimaryExpression(),
};
}
function parsePrimaryExpression(): any {
throw "Not implemented";
}
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
function foo() {
}
@@ -11,7 +11,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
function foo() {
}
@@ -28,7 +28,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
function foo() {
}
@@ -45,7 +45,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
function foo() {
}
@@ -62,7 +62,7 @@ namespace A {
return foo();
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
function foo() {
}
@@ -0,0 +1,45 @@
// ==ORIGINAL==
namespace N {
export const value = 1;
() => {
var f: () => number;
f = function (): number {
return value;
}
}
}
// ==SCOPE::namespace 'N'==
namespace N {
export const value = 1;
() => {
var f: () => number;
f = /*RENAME*/newFunction(f);
}
function newFunction(f: () => number) {
f = function(): number {
return value;
};
return f;
}
}
// ==SCOPE::global scope==
namespace N {
export const value = 1;
() => {
var f: () => number;
f = /*RENAME*/newFunction(f);
}
}
function newFunction(f: () => number) {
f = function(): number {
return N.value;
};
return f;
}
@@ -0,0 +1,46 @@
// ==ORIGINAL==
namespace N {
export const value = 1;
() => {
var c = class {
M() {
return value;
}
}
}
}
// ==SCOPE::namespace 'N'==
namespace N {
export const value = 1;
() => {
/*RENAME*/newFunction();
}
function newFunction() {
var c = class {
M() {
return value;
}
};
}
}
// ==SCOPE::global scope==
namespace N {
export const value = 1;
() => {
/*RENAME*/newFunction();
}
}
function newFunction() {
var c = class {
M() {
return N.value;
}
};
}
@@ -0,0 +1,19 @@
// ==ORIGINAL==
function F() {
function G() { }
}
// ==SCOPE::function 'F'==
function F() {
/*RENAME*/newFunction();
function newFunction() {
function G() { }
}
}
// ==SCOPE::global scope==
function F() {
/*RENAME*/newFunction();
}
function newFunction() {
function G() { }
}
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
function foo() {
}
@@ -13,7 +13,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
function foo() {
}
@@ -32,7 +32,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
function foo() {
}
@@ -51,7 +51,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
function foo() {
}
@@ -70,7 +70,7 @@ namespace A {
return foo();
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
function foo() {
}
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
let x = 1;
export function foo() {
@@ -14,7 +14,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
let x = 1;
export function foo() {
@@ -34,7 +34,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
let x = 1;
export function foo() {
@@ -55,7 +55,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
let x = 1;
export function foo() {
@@ -76,7 +76,7 @@ namespace A {
return a;
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
let x = 1;
export function foo() {
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
let x = 1;
export function foo() {
@@ -14,7 +14,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
let x = 1;
export function foo() {
@@ -34,7 +34,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
let x = 1;
export function foo() {
@@ -56,7 +56,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
let x = 1;
export function foo() {
@@ -78,7 +78,7 @@ namespace A {
return { __return: foo(), a };
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
let x = 1;
export function foo() {
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
let x = 1;
export namespace C {
@@ -16,7 +16,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
let x = 1;
export namespace C {
@@ -38,7 +38,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
let x = 1;
export namespace C {
@@ -62,7 +62,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
let x = 1;
export namespace C {
@@ -86,7 +86,7 @@ namespace A {
return { __return: C.foo(), a };
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
let x = 1;
export namespace C {
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
let x = 1;
namespace B {
@@ -8,7 +8,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
let x = 1;
namespace B {
@@ -22,7 +22,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
let x = 1;
namespace B {
@@ -36,7 +36,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
let x = 1;
namespace B {
@@ -50,7 +50,7 @@ namespace A {
return 1 + a1 + x;
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
let x = 1;
namespace B {
@@ -1,4 +1,4 @@
==ORIGINAL==
// ==ORIGINAL==
namespace A {
export interface I { x: number };
namespace B {
@@ -8,7 +8,7 @@ namespace A {
}
}
}
==SCOPE::function 'a'==
// ==SCOPE::function 'a'==
namespace A {
export interface I { x: number };
namespace B {
@@ -22,7 +22,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'B'==
// ==SCOPE::namespace 'B'==
namespace A {
export interface I { x: number };
namespace B {
@@ -36,7 +36,7 @@ namespace A {
}
}
}
==SCOPE::namespace 'A'==
// ==SCOPE::namespace 'A'==
namespace A {
export interface I { x: number };
namespace B {
@@ -50,7 +50,7 @@ namespace A {
return a1.x + 10;
}
}
==SCOPE::global scope==
// ==SCOPE::global scope==
namespace A {
export interface I { x: number };
namespace B {
@@ -1,98 +0,0 @@
==ORIGINAL==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
let a = 1;
let y = 5;
let z = x;
a = y;
foo();
}
}
}
==SCOPE::function a==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
let a = 1;
newFunction();
function newFunction() {
let y = 5;
let z = x;
a = y;
foo();
}
}
}
}
==SCOPE::namespace B==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
let a = 1;
({ a } = newFunction(a));
}
function newFunction(a: any) {
let y = 5;
let z = x;
a = y;
foo();
return { a };
}
}
}
==SCOPE::namespace A==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
let a = 1;
({ a } = newFunction(a));
}
}
function newFunction(a: any) {
let y = 5;
let z = x;
a = y;
foo();
return { a };
}
}
==SCOPE::file '/a.ts'==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
let a = 1;
({ a } = newFunction(x, a, foo));
}
}
}
function newFunction(x: any, a: any, foo: any) {
let y = 5;
let z = x;
a = y;
foo();
return { a };
}
@@ -1,70 +0,0 @@
==ORIGINAL==
namespace A {
export interface I { x: number };
class C {
a() {
let z = 1;
let a1: I = { x: 1 };
return a1.x + 10;
}
}
}
==SCOPE::method a==
namespace A {
export interface I { x: number };
class C {
a() {
let z = 1;
return newFunction();
function newFunction() {
let a1: I = { x: 1 };
return a1.x + 10;
}
}
}
}
==SCOPE::class C==
namespace A {
export interface I { x: number };
class C {
a() {
let z = 1;
return this.newFunction();
}
private newFunction() {
let a1: I = { x: 1 };
return a1.x + 10;
}
}
}
==SCOPE::namespace A==
namespace A {
export interface I { x: number };
class C {
a() {
let z = 1;
return newFunction();
}
}
function newFunction() {
let a1: I = { x: 1 };
return a1.x + 10;
}
}
==SCOPE::file '/a.ts'==
namespace A {
export interface I { x: number };
class C {
a() {
let z = 1;
return newFunction();
}
}
}
function newFunction() {
let a1: A.I = { x: 1 };
return a1.x + 10;
}
@@ -1,86 +0,0 @@
==ORIGINAL==
namespace A {
let y = 1;
class C {
a() {
let z = 1;
let a1 = { x: 1 };
y = 10;
z = 42;
return a1.x + 10;
}
}
}
==SCOPE::method a==
namespace A {
let y = 1;
class C {
a() {
let z = 1;
return newFunction();
function newFunction() {
let a1 = { x: 1 };
y = 10;
z = 42;
return a1.x + 10;
}
}
}
}
==SCOPE::class C==
namespace A {
let y = 1;
class C {
a() {
let z = 1;
var __return: any;
({ z, __return } = this.newFunction(z));
return __return;
}
private newFunction(z: any) {
let a1 = { x: 1 };
y = 10;
z = 42;
return { z, __return: a1.x + 10 };
}
}
}
==SCOPE::namespace A==
namespace A {
let y = 1;
class C {
a() {
let z = 1;
var __return: any;
({ z, __return } = newFunction(z));
return __return;
}
}
function newFunction(z: any) {
let a1 = { x: 1 };
y = 10;
z = 42;
return { z, __return: a1.x + 10 };
}
}
==SCOPE::file '/a.ts'==
namespace A {
let y = 1;
class C {
a() {
let z = 1;
var __return: any;
({ y, z, __return } = newFunction(y, z));
return __return;
}
}
}
function newFunction(y: any, z: any) {
let a1 = { x: 1 };
y = 10;
z = 42;
return { y, z, __return: a1.x + 10 };
}
@@ -1,36 +0,0 @@
==ORIGINAL==
namespace A {
let y = 1;
class C {
b() {}
a() {
let z = 1;
let a1 = { x: 1 };
y = 10;
z = 42;
this.b();
return a1.x + 10;
}
}
}
==SCOPE::class C==
namespace A {
let y = 1;
class C {
b() {}
a() {
let z = 1;
var __return: any;
({ z, __return } = this.newFunction(z));
return __return;
}
private newFunction(z: any) {
let a1 = { x: 1 };
y = 10;
z = 42;
this.b();
return { z, __return: a1.x + 10 };
}
}
}
@@ -1,85 +0,0 @@
==ORIGINAL==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
let y = 5;
let z = x;
return foo();
}
}
}
==SCOPE::function a==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
return newFunction();
function newFunction() {
let y = 5;
let z = x;
return foo();
}
}
}
}
==SCOPE::namespace B==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
return newFunction();
}
function newFunction() {
let y = 5;
let z = x;
return foo();
}
}
}
==SCOPE::namespace A==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
return newFunction();
}
}
function newFunction() {
let y = 5;
let z = x;
return foo();
}
}
==SCOPE::file '/a.ts'==
namespace A {
let x = 1;
function foo() {
}
namespace B {
function a() {
return newFunction(x, foo);
}
}
}
function newFunction(x: any, foo: any) {
let y = 5;
let z = x;
return foo();
}
@@ -1,80 +0,0 @@
==ORIGINAL==
namespace A {
function foo() {
}
namespace B {
function* a(z: number) {
let y = 5;
yield z;
return foo();
}
}
}
==SCOPE::function a==
namespace A {
function foo() {
}
namespace B {
function* a(z: number) {
return yield* newFunction();
function* newFunction() {
let y = 5;
yield z;
return foo();
}
}
}
}
==SCOPE::namespace B==
namespace A {
function foo() {
}
namespace B {
function* a(z: number) {
return yield* newFunction(z);
}
function* newFunction(z: any) {
let y = 5;
yield z;
return foo();
}
}
}
==SCOPE::namespace A==
namespace A {
function foo() {
}
namespace B {
function* a(z: number) {
return yield* newFunction(z);
}
}
function* newFunction(z: any) {
let y = 5;
yield z;
return foo();
}
}
==SCOPE::file '/a.ts'==
namespace A {
function foo() {
}
namespace B {
function* a(z: number) {
return yield* newFunction(z, foo);
}
}
}
function* newFunction(z: any, foo: any) {
let y = 5;
yield z;
return foo();
}
@@ -1,90 +0,0 @@
==ORIGINAL==
namespace A {
function foo() {
}
namespace B {
async function a(z: number, z1: any) {
let y = 5;
if (z) {
await z1;
}
return foo();
}
}
}
==SCOPE::function a==
namespace A {
function foo() {
}
namespace B {
async function a(z: number, z1: any) {
return await newFunction();
async function newFunction() {
let y = 5;
if (z) {
await z1;
}
return foo();
}
}
}
}
==SCOPE::namespace B==
namespace A {
function foo() {
}
namespace B {
async function a(z: number, z1: any) {
return await newFunction(z, z1);
}
async function newFunction(z: any, z1: any) {
let y = 5;
if (z) {
await z1;
}
return foo();
}
}
}
==SCOPE::namespace A==
namespace A {
function foo() {
}
namespace B {
async function a(z: number, z1: any) {
return await newFunction(z, z1);
}
}
async function newFunction(z: any, z1: any) {
let y = 5;
if (z) {
await z1;
}
return foo();
}
}
==SCOPE::file '/a.ts'==
namespace A {
function foo() {
}
namespace B {
async function a(z: number, z1: any) {
return await newFunction(z, z1, foo);
}
}
}
async function newFunction(z: any, z1: any, foo: any) {
let y = 5;
if (z) {
await z1;
}
return foo();
}
@@ -1,98 +0,0 @@
==ORIGINAL==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
let y = 5;
let z = x;
a = y;
foo();
}
}
}
==SCOPE::function a==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
newFunction();
function newFunction() {
let y = 5;
let z = x;
a = y;
foo();
}
}
}
}
==SCOPE::namespace B==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
({ a } = newFunction(a));
}
function newFunction(a: any) {
let y = 5;
let z = x;
a = y;
foo();
return { a };
}
}
}
==SCOPE::namespace A==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
({ a } = newFunction(a));
}
}
function newFunction(a: any) {
let y = 5;
let z = x;
a = y;
foo();
return { a };
}
}
==SCOPE::file '/a.ts'==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
({ a } = newFunction(x, a));
}
}
}
function newFunction(x: any, a: any) {
let y = 5;
let z = x;
a = y;
A.foo();
return { a };
}
-101
View File
@@ -1,101 +0,0 @@
==ORIGINAL==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
let y = 5;
let z = x;
a = y;
return foo();
}
}
}
==SCOPE::function a==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
return newFunction();
function newFunction() {
let y = 5;
let z = x;
a = y;
return foo();
}
}
}
}
==SCOPE::namespace B==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
var __return: any;
({ a, __return } = newFunction(a));
return __return;
}
function newFunction(a: any) {
let y = 5;
let z = x;
a = y;
return { a, __return: foo() };
}
}
}
==SCOPE::namespace A==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
var __return: any;
({ a, __return } = newFunction(a));
return __return;
}
}
function newFunction(a: any) {
let y = 5;
let z = x;
a = y;
return { a, __return: foo() };
}
}
==SCOPE::file '/a.ts'==
namespace A {
let x = 1;
export function foo() {
}
namespace B {
function a() {
let a = 1;
var __return: any;
({ a, __return } = newFunction(x, a));
return __return;
}
}
}
function newFunction(x: any, a: any) {
let y = 5;
let z = x;
a = y;
return { a, __return: A.foo() };
}
-111
View File
@@ -1,111 +0,0 @@
==ORIGINAL==
namespace A {
let x = 1;
export namespace C {
export function foo() {
}
}
namespace B {
function a() {
let a = 1;
let y = 5;
let z = x;
a = y;
return C.foo();
}
}
}
==SCOPE::function a==
namespace A {
let x = 1;
export namespace C {
export function foo() {
}
}
namespace B {
function a() {
let a = 1;
return newFunction();
function newFunction() {
let y = 5;
let z = x;
a = y;
return C.foo();
}
}
}
}
==SCOPE::namespace B==
namespace A {
let x = 1;
export namespace C {
export function foo() {
}
}
namespace B {
function a() {
let a = 1;
var __return: any;
({ a, __return } = newFunction(a));
return __return;
}
function newFunction(a: any) {
let y = 5;
let z = x;
a = y;
return { a, __return: C.foo() };
}
}
}
==SCOPE::namespace A==
namespace A {
let x = 1;
export namespace C {
export function foo() {
}
}
namespace B {
function a() {
let a = 1;
var __return: any;
({ a, __return } = newFunction(a));
return __return;
}
}
function newFunction(a: any) {
let y = 5;
let z = x;
a = y;
return { a, __return: C.foo() };
}
}
==SCOPE::file '/a.ts'==
namespace A {
let x = 1;
export namespace C {
export function foo() {
}
}
namespace B {
function a() {
let a = 1;
var __return: any;
({ a, __return } = newFunction(x, a));
return __return;
}
}
}
function newFunction(x: any, a: any) {
let y = 5;
let z = x;
a = y;
return { a, __return: A.C.foo() };
}
@@ -1,57 +0,0 @@
==ORIGINAL==
namespace A {
let x = 1;
namespace B {
function a() {
let a1 = 1;
return 1 + a1 + x + 100;
}
}
}
==SCOPE::function a==
namespace A {
let x = 1;
namespace B {
function a() {
let a1 = 1;
return newFunction() + 100;
function newFunction() { 1 + a1 + x; }
}
}
}
==SCOPE::namespace B==
namespace A {
let x = 1;
namespace B {
function a() {
let a1 = 1;
return newFunction(a1) + 100;
}
function newFunction(a1: any) { 1 + a1 + x; }
}
}
==SCOPE::namespace A==
namespace A {
let x = 1;
namespace B {
function a() {
let a1 = 1;
return newFunction(a1) + 100;
}
}
function newFunction(a1: any) { 1 + a1 + x; }
}
==SCOPE::file '/a.ts'==
namespace A {
let x = 1;
namespace B {
function a() {
let a1 = 1;
return newFunction(a1, x) + 100;
}
}
}
function newFunction(a1: any, x: any) { 1 + a1 + x; }
@@ -1,65 +0,0 @@
==ORIGINAL==
namespace A {
export interface I { x: number };
namespace B {
function a() {
let a1: I = { x: 1 };
return a1.x + 10;
}
}
}
==SCOPE::function a==
namespace A {
export interface I { x: number };
namespace B {
function a() {
return newFunction();
function newFunction() {
let a1: I = { x: 1 };
return a1.x + 10;
}
}
}
}
==SCOPE::namespace B==
namespace A {
export interface I { x: number };
namespace B {
function a() {
return newFunction();
}
function newFunction() {
let a1: I = { x: 1 };
return a1.x + 10;
}
}
}
==SCOPE::namespace A==
namespace A {
export interface I { x: number };
namespace B {
function a() {
return newFunction();
}
}
function newFunction() {
let a1: I = { x: 1 };
return a1.x + 10;
}
}
==SCOPE::file '/a.ts'==
namespace A {
export interface I { x: number };
namespace B {
function a() {
return newFunction();
}
}
}
function newFunction() {
let a1: A.I = { x: 1 };
return a1.x + 10;
}
@@ -1,8 +1,5 @@
/// <reference path='fourslash.ts' />
// TODO: GH#18546
// For now this tests that at least we don't crash.
////function f() {
//// /*start*/namespace N {}/*end*/
////}
@@ -13,9 +10,9 @@ edit.applyRefactor({
actionName: "scope_1",
actionDescription: "Extract function into global scope",
newContent: `function f() {
/*RENAME*/newFunction(N);
/*RENAME*/newFunction();
}
function newFunction(N: any) {
function newFunction() {
namespace N { }
}
`
+6 -6
View File
@@ -5,7 +5,7 @@
//// class C {
//// static j = /*c*/1 + 1/*d*/;
//// constructor(q: string = /*a*/"a" + "b"/*b*/) {
//// constructor(q: string = /*a*/"hello"/*b*/) {
//// }
//// }
@@ -21,7 +21,7 @@ edit.applyRefactor({
}
private static newFunction(): string {
return "a" + "b";
return "hello";
}
}`
});
@@ -37,12 +37,12 @@ edit.applyRefactor({
constructor(q: string = C.newFunction()) {
}
private static newFunction(): string {
return "a" + "b";
}
private static newFunction_1() {
return 1 + 1;
}
private static newFunction(): string {
return "hello";
}
}`
});
+2 -2
View File
@@ -3,7 +3,7 @@
// You cannot extract a function initializer into the function's body.
// The innermost scope (scope_0) is the sibling of the function, not the function itself.
//// function fn(x = /*a*/1 + 1/*b*/) {
//// function fn(x = /*a*/3/*b*/) {
//// }
goTo.select('a', 'b');
@@ -15,7 +15,7 @@ edit.applyRefactor({
`function fn(x = /*RENAME*/newFunction()) {
}
function newFunction() {
return 1 + 1;
return 3;
}
`
});