* 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, rangeFacts, context)
| 160923 | * Stores either a list of changes that should be applied to extract a range or a list of errors |
| 160924 | */ |
| 160925 | function extractConstantInScope(node, scope, _a, rangeFacts, context) { |
| 160926 | var _b; |
| 160927 | var substitutions = _a.substitutions; |
| 160928 | var checker = context.program.getTypeChecker(); |
| 160929 | // Make a unique name for the extracted variable |
| 160930 | var file = scope.getSourceFile(); |
| 160931 | var localNameText = ts.isPropertyAccessExpression(node) && !ts.isClassLike(scope) && !checker.resolveName(node.name.text, node, 111551 /* SymbolFlags.Value */, /*excludeGlobals*/ false) && !ts.isPrivateIdentifier(node.name) && !ts.isKeyword(node.name.originalKeywordKind) |
| 160932 | ? node.name.text |
| 160933 | : ts.getUniqueName(ts.isClassLike(scope) ? "newProperty" : "newLocal", file); |
| 160934 | var isJS = ts.isInJSFile(scope); |
| 160935 | var variableType = isJS || !checker.isContextSensitive(node) |
| 160936 | ? undefined |
| 160937 | : checker.typeToTypeNode(checker.getContextualType(node), scope, 1 /* NodeBuilderFlags.NoTruncation */); // TODO: GH#18217 |
| 160938 | var initializer = transformConstantInitializer(ts.skipParentheses(node), substitutions); |
| 160939 | (_b = transformFunctionInitializerAndType(variableType, initializer), variableType = _b.variableType, initializer = _b.initializer); |
| 160940 | ts.suppressLeadingAndTrailingTrivia(initializer); |
| 160941 | var changeTracker = ts.textChanges.ChangeTracker.fromContext(context); |
| 160942 | if (ts.isClassLike(scope)) { |
| 160943 | ts.Debug.assert(!isJS, "Cannot extract to a JS class"); // See CannotExtractToJSClass |
| 160944 | var modifiers = []; |
| 160945 | modifiers.push(ts.factory.createModifier(121 /* SyntaxKind.PrivateKeyword */)); |
| 160946 | if (rangeFacts & RangeFacts.InStaticRegion) { |
| 160947 | modifiers.push(ts.factory.createModifier(124 /* SyntaxKind.StaticKeyword */)); |
| 160948 | } |
| 160949 | modifiers.push(ts.factory.createModifier(145 /* SyntaxKind.ReadonlyKeyword */)); |
| 160950 | var newVariable = ts.factory.createPropertyDeclaration( |
| 160951 | /*decorators*/ undefined, modifiers, localNameText, |
| 160952 | /*questionToken*/ undefined, variableType, initializer); |
| 160953 | var localReference = ts.factory.createPropertyAccessExpression(rangeFacts & RangeFacts.InStaticRegion |
| 160954 | ? ts.factory.createIdentifier(scope.name.getText()) // TODO: GH#18217 |
| 160955 | : ts.factory.createThis(), ts.factory.createIdentifier(localNameText)); |
| 160956 | if (isInJSXContent(node)) { |
| 160957 | localReference = ts.factory.createJsxExpression(/*dotDotDotToken*/ undefined, localReference); |
| 160958 | } |
| 160959 | // Declare |
| 160960 | var maxInsertionPos = node.pos; |
| 160961 | var nodeToInsertBefore = getNodeToInsertPropertyBefore(maxInsertionPos, scope); |
| 160962 | changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, /*blankLineBetween*/ true); |
| 160963 | // Consume |
| 160964 | changeTracker.replaceNode(context.file, node, localReference); |
| 160965 | } |
| 160966 | else { |
| 160967 | var newVariableDeclaration = ts.factory.createVariableDeclaration(localNameText, /*exclamationToken*/ undefined, variableType, initializer); |
| 160968 | // If the node is part of an initializer in a list of variable declarations, insert a new |
| 160969 | // variable declaration into the list (in case it depends on earlier ones). |
| 160970 | // CONSIDER: If the declaration list isn't const, we might want to split it into multiple |
| 160971 | // lists so that the newly extracted one can be const. |
| 160972 | var oldVariableDeclaration = getContainingVariableDeclarationIfInList(node, scope); |
| 160973 | if (oldVariableDeclaration) { |
| 160974 | // Declare |
| 160975 | // CONSIDER: could detect that each is on a separate line (See `extractConstant_VariableList_MultipleLines` in `extractConstants.ts`) |
| 160976 | changeTracker.insertNodeBefore(context.file, oldVariableDeclaration, newVariableDeclaration); |
| 160977 | // Consume |
| 160978 | var localReference = ts.factory.createIdentifier(localNameText); |
| 160979 | changeTracker.replaceNode(context.file, node, localReference); |
| 160980 | } |
| 160981 | else if (node.parent.kind === 238 /* SyntaxKind.ExpressionStatement */ && scope === ts.findAncestor(node, isScope)) { |
| 160982 | // If the parent is an expression statement and the target scope is the immediately enclosing one, |
no test coverage detected
searching dependent graphs…