Skip to content

Commit c688f99

Browse files
author
Andy Hanson
committed
convertToAsyncFunction: Use ReadonlyArray / ReadonlyMap where possible
1 parent 6adb9d1 commit c688f99

File tree

1 file changed

+41
-41
lines changed

1 file changed

+41
-41
lines changed

src/services/codefixes/convertToAsyncFunction.ts

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ namespace ts.codefix {
1515
});
1616

1717
interface SynthIdentifier {
18-
identifier: Identifier;
19-
types: Type[];
18+
readonly identifier: Identifier;
19+
readonly types: Type[];
2020
numberOfAssignmentsOriginal: number; // number of times the variable should be assigned in the refactor
2121
}
2222

2323
interface SymbolAndIdentifier {
24-
identifier: Identifier;
25-
symbol: Symbol;
24+
readonly identifier: Identifier;
25+
readonly symbol: Symbol;
2626
}
2727

2828
interface Transformer {
29-
checker: TypeChecker;
30-
synthNamesMap: Map<SynthIdentifier>; // keys are the symbol id of the identifier
31-
allVarNames: SymbolAndIdentifier[];
32-
setOfExpressionsToReturn: Map<true>; // keys are the node ids of the expressions
33-
constIdentifiers: Identifier[];
34-
originalTypeMap: Map<Type>; // keys are the node id of the identifier
35-
isInJSFile: boolean;
29+
readonly checker: TypeChecker;
30+
readonly synthNamesMap: Map<SynthIdentifier>; // keys are the symbol id of the identifier
31+
readonly allVarNames: ReadonlyArray<SymbolAndIdentifier>;
32+
readonly setOfExpressionsToReturn: ReadonlyMap<true>; // keys are the node ids of the expressions
33+
readonly constIdentifiers: Identifier[];
34+
readonly originalTypeMap: ReadonlyMap<Type>; // keys are the node id of the identifier
35+
readonly isInJSFile: boolean;
3636
}
3737

3838
function convertToAsyncFunction(changes: textChanges.ChangeTracker, sourceFile: SourceFile, position: number, checker: TypeChecker, context: CodeFixContextBase): void {
@@ -61,7 +61,7 @@ namespace ts.codefix {
6161
const functionToConvertRenamed: FunctionLikeDeclaration = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context, setOfExpressionsToReturn, originalTypeMap, allVarNames);
6262
const constIdentifiers = getConstIdentifiers(synthNamesMap);
6363
const returnStatements = getReturnStatementsWithPromiseHandlers(functionToConvertRenamed);
64-
const transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile: isInJavascript };
64+
const transformer: Transformer = { checker, synthNamesMap, allVarNames, setOfExpressionsToReturn, constIdentifiers, originalTypeMap, isInJSFile: isInJavascript };
6565

6666
if (!returnStatements.length) {
6767
return;
@@ -88,7 +88,7 @@ namespace ts.codefix {
8888
}
8989

9090
// Returns the identifiers that are never reassigned in the refactor
91-
function getConstIdentifiers(synthNamesMap: Map<SynthIdentifier>): Identifier[] {
91+
function getConstIdentifiers(synthNamesMap: ReadonlyMap<SynthIdentifier>): Identifier[] {
9292
const constIdentifiers: Identifier[] = [];
9393
synthNamesMap.forEach((val) => {
9494
if (val.numberOfAssignmentsOriginal === 0) {
@@ -249,18 +249,18 @@ namespace ts.codefix {
249249
}
250250
}
251251

252-
function getNewNameIfConflict(name: Identifier, originalNames: Map<Symbol[]>): SynthIdentifier {
253-
const numVarsSameName = (originalNames.get(name.text) || []).length;
252+
function getNewNameIfConflict(name: Identifier, originalNames: ReadonlyMap<Symbol[]>): SynthIdentifier {
253+
const numVarsSameName = (originalNames.get(name.text) || emptyArray).length;
254254
const numberOfAssignmentsOriginal = 0;
255255
const identifier = numVarsSameName === 0 ? name : createIdentifier(name.text + "_" + numVarsSameName);
256256
return { identifier, types: [], numberOfAssignmentsOriginal };
257257
}
258258

259259
// dispatch function to recursively build the refactoring
260260
// should be kept up to date with isFixablePromiseHandler in suggestionDiagnostics.ts
261-
function transformExpression(node: Expression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): Statement[] {
261+
function transformExpression(node: Expression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
262262
if (!node) {
263-
return [];
263+
return emptyArray;
264264
}
265265

266266
const originalType = isIdentifier(node) && transformer.originalTypeMap.get(getNodeId(node).toString());
@@ -280,10 +280,10 @@ namespace ts.codefix {
280280
}
281281

282282
codeActionSucceeded = false;
283-
return [];
283+
return emptyArray;
284284
}
285285

286-
function transformCatch(node: CallExpression, transformer: Transformer, prevArgName?: SynthIdentifier): Statement[] {
286+
function transformCatch(node: CallExpression, transformer: Transformer, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
287287
const func = node.arguments[0];
288288
const argName = getArgName(func, transformer);
289289
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(node).toString());
@@ -336,7 +336,7 @@ namespace ts.codefix {
336336
return newSynthName;
337337
}
338338

339-
function transformThen(node: CallExpression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): Statement[] {
339+
function transformThen(node: CallExpression, transformer: Transformer, outermostParent: CallExpression, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
340340
const [res, rej] = node.arguments;
341341

342342
if (!res) {
@@ -356,23 +356,23 @@ namespace ts.codefix {
356356
const catchArg = argNameRej ? argNameRej.identifier.text : "e";
357357
const catchClause = createCatchClause(catchArg, createBlock(transformationBody2));
358358

359-
return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined) as Statement];
359+
return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined)];
360360
}
361361

362362
return transformExpression(node.expression, transformer, node, argNameRes).concat(transformationBody);
363363
}
364364

365-
function getFlagOfIdentifier(node: Identifier, constIdentifiers: Identifier[]): NodeFlags {
365+
function getFlagOfIdentifier(node: Identifier, constIdentifiers: ReadonlyArray<Identifier>): NodeFlags {
366366
const inArr: boolean = constIdentifiers.some(elem => elem.text === node.text);
367367
return inArr ? NodeFlags.Const : NodeFlags.Let;
368368
}
369369

370-
function transformPromiseCall(node: Expression, transformer: Transformer, prevArgName?: SynthIdentifier): Statement[] {
370+
function transformPromiseCall(node: Expression, transformer: Transformer, prevArgName?: SynthIdentifier): ReadonlyArray<Statement> {
371371
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(node).toString());
372372
// the identifier is empty when the handler (.then()) ignores the argument - In this situation we do not need to save the result of the promise returning call
373373
const originalNodeParent = node.original ? node.original.parent : node.parent;
374374
if (prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
375-
return createTransformedStatement(prevArgName, createAwait(node), transformer).concat(); // hack to make the types match
375+
return createTransformedStatement(prevArgName, createAwait(node), transformer);
376376
}
377377
else if (!prevArgName && !shouldReturn && (!originalNodeParent || isPropertyAccessExpression(originalNodeParent))) {
378378
return [createStatement(createAwait(node))];
@@ -381,23 +381,23 @@ namespace ts.codefix {
381381
return [createReturn(getSynthesizedDeepClone(node))];
382382
}
383383

384-
function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): NodeArray<Statement> {
384+
function createTransformedStatement(prevArgName: SynthIdentifier | undefined, rightHandSide: Expression, transformer: Transformer): ReadonlyArray<Statement> {
385385
if (!prevArgName || prevArgName.identifier.text.length === 0) {
386386
// if there's no argName to assign to, there still might be side effects
387-
return createNodeArray([createStatement(rightHandSide)]);
387+
return [createStatement(rightHandSide)];
388388
}
389389

390390
if (prevArgName.types.length < prevArgName.numberOfAssignmentsOriginal) {
391391
// if the variable has already been declared, we don't need "let" or "const"
392-
return createNodeArray([createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))]);
392+
return [createStatement(createAssignment(getSynthesizedDeepClone(prevArgName.identifier), rightHandSide))];
393393
}
394394

395-
return createNodeArray([createVariableStatement(/*modifiers*/ undefined,
396-
(createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepClone(prevArgName.identifier), /*type*/ undefined, rightHandSide)], getFlagOfIdentifier(prevArgName.identifier, transformer.constIdentifiers))))]);
395+
return [createVariableStatement(/*modifiers*/ undefined,
396+
(createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepClone(prevArgName.identifier), /*type*/ undefined, rightHandSide)], getFlagOfIdentifier(prevArgName.identifier, transformer.constIdentifiers))))];
397397
}
398398

399399
// should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts
400-
function getTransformationBody(func: Expression, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier | undefined, parent: CallExpression, transformer: Transformer): NodeArray<Statement> {
400+
function getTransformationBody(func: Expression, prevArgName: SynthIdentifier | undefined, argName: SynthIdentifier | undefined, parent: CallExpression, transformer: Transformer): ReadonlyArray<Statement> {
401401

402402
const shouldReturn = transformer.setOfExpressionsToReturn.get(getNodeId(parent).toString());
403403
switch (func.kind) {
@@ -407,9 +407,9 @@ namespace ts.codefix {
407407
case SyntaxKind.Identifier: // identifier includes undefined
408408
if (!argName) break;
409409

410-
const synthCall = createCall(getSynthesizedDeepClone(func) as Identifier, /*typeArguments*/ undefined, argName ? [argName.identifier] : []);
410+
const synthCall = createCall(getSynthesizedDeepClone(func as Identifier), /*typeArguments*/ undefined, argName ? [argName.identifier] : emptyArray);
411411
if (shouldReturn) {
412-
return createNodeArray([createReturn(synthCall)]);
412+
return [createReturn(synthCall)];
413413
}
414414

415415
const type = transformer.originalTypeMap.get(getNodeId(func).toString()) || transformer.checker.getTypeAtLocation(func);
@@ -447,15 +447,15 @@ namespace ts.codefix {
447447
}
448448
}
449449

450-
return shouldReturn ? getSynthesizedDeepClones(createNodeArray(refactoredStmts)) :
451-
removeReturns(createNodeArray(refactoredStmts), prevArgName!.identifier, transformer, seenReturnStatement);
450+
return shouldReturn ? refactoredStmts.map(s => getSynthesizedDeepClone(s)) :
451+
removeReturns(refactoredStmts, prevArgName!.identifier, transformer, seenReturnStatement);
452452
}
453453
else {
454454
const innerRetStmts = getReturnStatementsWithPromiseHandlers(createReturn(funcBody));
455455
const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName);
456456

457457
if (innerCbBody.length > 0) {
458-
return createNodeArray(innerCbBody);
458+
return innerCbBody;
459459
}
460460

461461
if (!shouldReturn) {
@@ -470,7 +470,7 @@ namespace ts.codefix {
470470
return transformedStatement;
471471
}
472472
else {
473-
return createNodeArray([createReturn(getSynthesizedDeepClone(funcBody))]);
473+
return [createReturn(getSynthesizedDeepClone(funcBody))];
474474
}
475475
}
476476
}
@@ -479,7 +479,7 @@ namespace ts.codefix {
479479
codeActionSucceeded = false;
480480
break;
481481
}
482-
return createNodeArray([]);
482+
return emptyArray;
483483
}
484484

485485
function getLastCallSignature(type: Type, checker: TypeChecker): Signature | undefined {
@@ -488,7 +488,7 @@ namespace ts.codefix {
488488
}
489489

490490

491-
function removeReturns(stmts: NodeArray<Statement>, prevArgName: Identifier, transformer: Transformer, seenReturnStatement: boolean): NodeArray<Statement> {
491+
function removeReturns(stmts: ReadonlyArray<Statement>, prevArgName: Identifier, transformer: Transformer, seenReturnStatement: boolean): ReadonlyArray<Statement> {
492492
const ret: Statement[] = [];
493493
for (const stmt of stmts) {
494494
if (isReturnStatement(stmt)) {
@@ -509,15 +509,15 @@ namespace ts.codefix {
509509
(createVariableDeclarationList([createVariableDeclaration(prevArgName, /*type*/ undefined, createIdentifier("undefined"))], getFlagOfIdentifier(prevArgName, transformer.constIdentifiers)))));
510510
}
511511

512-
return createNodeArray(ret);
512+
return ret;
513513
}
514514

515515

516-
function getInnerTransformationBody(transformer: Transformer, innerRetStmts: Node[], prevArgName?: SynthIdentifier) {
516+
function getInnerTransformationBody(transformer: Transformer, innerRetStmts: ReadonlyArray<Node>, prevArgName?: SynthIdentifier) {
517517

518518
let innerCbBody: Statement[] = [];
519519
for (const stmt of innerRetStmts) {
520-
forEachChild(stmt, function visit(node: Node) {
520+
forEachChild(stmt, function visit(node) {
521521
if (isCallExpression(node)) {
522522
const temp = transformExpression(node, transformer, node, prevArgName);
523523
innerCbBody = innerCbBody.concat(temp);

0 commit comments

Comments
 (0)