* Result of 'extractRange' operation for a specific scope. * Stores either a list of changes that should be applied to extract a range or a list of errors
(node, scope, _a, exposedVariableDeclarations, range, context)
| 160688 | * Stores either a list of changes that should be applied to extract a range or a list of errors |
| 160689 | */ |
| 160690 | function extractFunctionInScope(node, scope, _a, exposedVariableDeclarations, range, context) { |
| 160691 | var usagesInScope = _a.usages, typeParameterUsages = _a.typeParameterUsages, substitutions = _a.substitutions; |
| 160692 | var checker = context.program.getTypeChecker(); |
| 160693 | var scriptTarget = ts.getEmitScriptTarget(context.program.getCompilerOptions()); |
| 160694 | var importAdder = ts.codefix.createImportAdder(context.file, context.program, context.preferences, context.host); |
| 160695 | // Make a unique name for the extracted function |
| 160696 | var file = scope.getSourceFile(); |
| 160697 | var functionNameText = ts.getUniqueName(ts.isClassLike(scope) ? "newMethod" : "newFunction", file); |
| 160698 | var isJS = ts.isInJSFile(scope); |
| 160699 | var functionName = ts.factory.createIdentifier(functionNameText); |
| 160700 | var returnType; |
| 160701 | var parameters = []; |
| 160702 | var callArguments = []; |
| 160703 | var writes; |
| 160704 | usagesInScope.forEach(function (usage, name) { |
| 160705 | var typeNode; |
| 160706 | if (!isJS) { |
| 160707 | var type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node); |
| 160708 | // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" |
| 160709 | type = checker.getBaseTypeOfLiteralType(type); |
| 160710 | typeNode = ts.codefix.typeToAutoImportableTypeNode(checker, importAdder, type, scope, scriptTarget, 1 /* NodeBuilderFlags.NoTruncation */); |
| 160711 | } |
| 160712 | var paramDecl = ts.factory.createParameterDeclaration( |
| 160713 | /*decorators*/ undefined, |
| 160714 | /*modifiers*/ undefined, |
| 160715 | /*dotDotDotToken*/ undefined, |
| 160716 | /*name*/ name, |
| 160717 | /*questionToken*/ undefined, typeNode); |
| 160718 | parameters.push(paramDecl); |
| 160719 | if (usage.usage === 2 /* Usage.Write */) { |
| 160720 | (writes || (writes = [])).push(usage); |
| 160721 | } |
| 160722 | callArguments.push(ts.factory.createIdentifier(name)); |
| 160723 | }); |
| 160724 | var typeParametersAndDeclarations = ts.arrayFrom(typeParameterUsages.values()).map(function (type) { return ({ type: type, declaration: getFirstDeclaration(type) }); }); |
| 160725 | var sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder); |
| 160726 | var typeParameters = sortedTypeParametersAndDeclarations.length === 0 |
| 160727 | ? undefined |
| 160728 | : sortedTypeParametersAndDeclarations.map(function (t) { return t.declaration; }); |
| 160729 | // Strictly speaking, we should check whether each name actually binds to the appropriate type |
| 160730 | // parameter. In cases of shadowing, they may not. |
| 160731 | var callTypeArguments = typeParameters !== undefined |
| 160732 | ? typeParameters.map(function (decl) { return ts.factory.createTypeReferenceNode(decl.name, /*typeArguments*/ undefined); }) |
| 160733 | : undefined; |
| 160734 | // Provide explicit return types for contextually-typed functions |
| 160735 | // to avoid problems when there are literal types present |
| 160736 | if (ts.isExpression(node) && !isJS) { |
| 160737 | var contextualType = checker.getContextualType(node); |
| 160738 | returnType = checker.typeToTypeNode(contextualType, scope, 1 /* NodeBuilderFlags.NoTruncation */); // TODO: GH#18217 |
| 160739 | } |
| 160740 | var _b = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty; |
| 160741 | ts.suppressLeadingAndTrailingTrivia(body); |
| 160742 | var newFunction; |
| 160743 | var callThis = !!(range.facts & RangeFacts.UsesThisInFunction); |
| 160744 | if (ts.isClassLike(scope)) { |
| 160745 | // always create private method in TypeScript files |
| 160746 | var modifiers = isJS ? [] : [ts.factory.createModifier(121 /* SyntaxKind.PrivateKeyword */)]; |
| 160747 | if (range.facts & RangeFacts.InStaticRegion) { |
no test coverage detected
searching dependent graphs…