From 9aeeae54b0af3942a4ba24eeb4cb8ab60e513cfc Mon Sep 17 00:00:00 2001 From: Gabriela Britto Date: Tue, 15 Jan 2019 16:56:53 -0800 Subject: [PATCH] create refactoring for converting to named parameters --- .../refactors/convertToNamedParameters.ts | 94 +++++++++++++++++++ src/services/tsconfig.json | 1 + 2 files changed, 95 insertions(+) create mode 100644 src/services/refactors/convertToNamedParameters.ts diff --git a/src/services/refactors/convertToNamedParameters.ts b/src/services/refactors/convertToNamedParameters.ts new file mode 100644 index 00000000000..dd4e4326737 --- /dev/null +++ b/src/services/refactors/convertToNamedParameters.ts @@ -0,0 +1,94 @@ +/* @internal */ +namespace ts.refactor.convertToNamedParameters { + const refactorName = "Convert to named parameters"; + const refactorDescription = "Convert to named parameters"; + const actionNameNamedParameters = "Convert to named parameters"; + const actionDescriptionNamedParameters = "Convert to named parameters"; + const minimumParameterLength = 3; + const paramTypeNamePostfix = "Param"; + registerRefactor(refactorName, { getEditsForAction, getAvailableActions }); + + + function getAvailableActions(context: RefactorContext): ReadonlyArray { + const { file, startPosition } = context; + const func = getFunctionDeclarationAtPosition(file, startPosition); + if (!func) return emptyArray; + + return [{ + name: refactorName, + description: refactorDescription, + actions: [{ + name: actionNameNamedParameters, + description: actionDescriptionNamedParameters + }] + }]; + } + + function getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { + Debug.assert(actionName === actionNameNamedParameters); + const { file, startPosition } = context; + const func = getFunctionDeclarationAtPosition(file, startPosition); + if (!func) return undefined; + + const paramTypeDeclaration = createParamTypeDeclaration(func); + return undefined; + } + + function getFunctionDeclarationAtPosition(file: SourceFile, startPosition: number): ValidFunctionDeclaration | undefined { + const node = getTokenAtPosition(file, startPosition); + const func = getContainingFunction(node); + if (!func || !isValidFunctionDeclaration(func)) return undefined; + return func; + } + + function isValidFunctionDeclaration(func: SignatureDeclaration): func is ValidFunctionDeclaration { + switch (func.kind) { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + if (func.name && func.parameters && func.parameters.length > minimumParameterLength) { + return true; + } + break; + default: + } + return false; + } + + function createParamTypeDeclaration(func: ValidFunctionDeclaration): InterfaceDeclaration { + const paramTypeName = getFunctionName(func); + const paramTypeMembers = + ts.map(func.parameters, + (paramDecl, _i) => createPropertySignatureFromParameterDeclaration(paramDecl)); + return createInterfaceDeclaration( + /* decorators */ undefined, + /* modifiers */ undefined, + createIdentifier(paramTypeName), + /* type parameters */ undefined, + /* heritage clauses */ undefined, + createNodeArray(paramTypeMembers)); + } + + function getFunctionName(func: ValidFunctionDeclaration): string { + return entityNameToString(func.name) + paramTypeNamePostfix; + } + + function createPropertySignatureFromParameterDeclaration(paramDeclaration: ValidParameterDeclaration): PropertySignature { + return createPropertySignature( + /*modifiers*/ undefined, + paramDeclaration.name, + paramDeclaration.questionToken, + paramDeclaration.type, + paramDeclaration.initializer); + } + + interface ValidFunctionDeclaration extends FunctionDeclaration { + name: Identifier; + body?: FunctionBody; + typeParameters?: NodeArray; + parameters: NodeArray; + } + + interface ValidParameterDeclaration extends ParameterDeclaration { + name: Identifier; + } +} \ No newline at end of file diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 21be663055a..793089e62c8 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -84,6 +84,7 @@ "refactors/generateGetAccessorAndSetAccessor.ts", "refactors/moveToNewFile.ts", "refactors/addOrRemoveBracesToArrowFunction.ts", + "refactors/convertToNamedParameters.ts", "services.ts", "breakpoints.ts", "transform.ts",