mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Update LKG
This commit is contained in:
+5
-4
@@ -11088,7 +11088,8 @@ var ts;
|
||||
return token() === 24 ||
|
||||
isIdentifierOrPattern() ||
|
||||
ts.isModifierKind(token()) ||
|
||||
token() === 57 || isStartOfType();
|
||||
token() === 57 ||
|
||||
isStartOfType(true);
|
||||
}
|
||||
function parseParameter() {
|
||||
var node = createNode(146);
|
||||
@@ -11427,7 +11428,7 @@ var ts;
|
||||
return parseTypeReference();
|
||||
}
|
||||
}
|
||||
function isStartOfType() {
|
||||
function isStartOfType(inStartOfParameter) {
|
||||
switch (token()) {
|
||||
case 119:
|
||||
case 136:
|
||||
@@ -11454,9 +11455,9 @@ var ts;
|
||||
case 39:
|
||||
return true;
|
||||
case 38:
|
||||
return lookAhead(nextTokenIsNumericLiteral);
|
||||
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
|
||||
case 19:
|
||||
return lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
|
||||
+115
-106
@@ -12958,7 +12958,8 @@ var ts;
|
||||
return token() === 24 ||
|
||||
isIdentifierOrPattern() ||
|
||||
ts.isModifierKind(token()) ||
|
||||
token() === 57 || isStartOfType();
|
||||
token() === 57 ||
|
||||
isStartOfType(true);
|
||||
}
|
||||
function parseParameter() {
|
||||
var node = createNode(146);
|
||||
@@ -13297,7 +13298,7 @@ var ts;
|
||||
return parseTypeReference();
|
||||
}
|
||||
}
|
||||
function isStartOfType() {
|
||||
function isStartOfType(inStartOfParameter) {
|
||||
switch (token()) {
|
||||
case 119:
|
||||
case 136:
|
||||
@@ -13324,9 +13325,9 @@ var ts;
|
||||
case 39:
|
||||
return true;
|
||||
case 38:
|
||||
return lookAhead(nextTokenIsNumericLiteral);
|
||||
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
|
||||
case 19:
|
||||
return lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
@@ -74425,7 +74426,9 @@ var ts;
|
||||
deleteCallback();
|
||||
}
|
||||
return {
|
||||
edits: changeTracker.getChanges()
|
||||
edits: changeTracker.getChanges(),
|
||||
renameFilename: undefined,
|
||||
renameLocation: undefined,
|
||||
};
|
||||
function deleteNode(node, inList) {
|
||||
if (inList === void 0) { inList = false; }
|
||||
@@ -74576,11 +74579,11 @@ var ts;
|
||||
var usedNames = ts.createMap();
|
||||
var i = 0;
|
||||
for (var _i = 0, extractions_1 = extractions; _i < extractions_1.length; _i++) {
|
||||
var extr = extractions_1[_i];
|
||||
if (extr.errors && extr.errors.length) {
|
||||
var _a = extractions_1[_i], scopeDescription = _a.scopeDescription, errors = _a.errors;
|
||||
if (errors.length) {
|
||||
continue;
|
||||
}
|
||||
var description = ts.formatStringFromArgs(ts.Diagnostics.Extract_function_into_0.message, [extr.scopeDescription]);
|
||||
var description = ts.formatStringFromArgs(ts.Diagnostics.Extract_function_into_0.message, [scopeDescription]);
|
||||
if (!usedNames.has(description)) {
|
||||
usedNames.set(description, true);
|
||||
actions.push({
|
||||
@@ -74608,9 +74611,7 @@ var ts;
|
||||
ts.Debug.assert(!!parsedIndexMatch, "Scope name should have matched the regexp");
|
||||
var index = +parsedIndexMatch[1];
|
||||
ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the scope index");
|
||||
var extractions = getPossibleExtractions(targetRange, context, index);
|
||||
ts.Debug.assert(extractions !== undefined, "The extraction went missing? How?");
|
||||
return ({ edits: extractions[0].changes });
|
||||
return getExtractionAtIndex(targetRange, context, index);
|
||||
}
|
||||
var Messages;
|
||||
(function (Messages) {
|
||||
@@ -74639,7 +74640,7 @@ var ts;
|
||||
RangeFacts[RangeFacts["IsAsyncFunction"] = 4] = "IsAsyncFunction";
|
||||
RangeFacts[RangeFacts["UsesThis"] = 8] = "UsesThis";
|
||||
RangeFacts[RangeFacts["InStaticRegion"] = 16] = "InStaticRegion";
|
||||
})(RangeFacts = extractMethod_1.RangeFacts || (extractMethod_1.RangeFacts = {}));
|
||||
})(RangeFacts || (RangeFacts = {}));
|
||||
function getRangeToExtract(sourceFile, span) {
|
||||
var length = span.length || 0;
|
||||
var start = getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, false), sourceFile, span);
|
||||
@@ -74879,7 +74880,7 @@ var ts;
|
||||
return undefined;
|
||||
}
|
||||
function isValidExtractionTarget(node) {
|
||||
return (node.kind === 228) || ts.isSourceFile(node) || isModuleBlock(node) || ts.isClassLike(node);
|
||||
return (node.kind === 228) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node);
|
||||
}
|
||||
function collectEnclosingScopes(range) {
|
||||
var current = isReadonlyArray(range.range) ? ts.firstOrUndefined(range.range) : range.range;
|
||||
@@ -74904,9 +74905,21 @@ var ts;
|
||||
}
|
||||
return scopes;
|
||||
}
|
||||
extractMethod_1.collectEnclosingScopes = collectEnclosingScopes;
|
||||
function getPossibleExtractions(targetRange, context, requestedChangesIndex) {
|
||||
if (requestedChangesIndex === void 0) { requestedChangesIndex = undefined; }
|
||||
function getExtractionAtIndex(targetRange, context, requestedChangesIndex) {
|
||||
var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, errorsPerScope = _b.errorsPerScope;
|
||||
ts.Debug.assert(!errorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context);
|
||||
}
|
||||
extractMethod_1.getExtractionAtIndex = getExtractionAtIndex;
|
||||
function getPossibleExtractions(targetRange, context) {
|
||||
var extractions = getPossibleExtractionsWorker(targetRange, context);
|
||||
return extractions && extractions.scopes.map(function (scope, i) {
|
||||
return ({ scopeDescription: getDescriptionForScope(scope), errors: extractions.readsAndWrites.errorsPerScope[i] });
|
||||
});
|
||||
}
|
||||
extractMethod_1.getPossibleExtractions = getPossibleExtractions;
|
||||
function getPossibleExtractionsWorker(targetRange, context) {
|
||||
var sourceFile = context.file;
|
||||
if (targetRange === undefined) {
|
||||
return undefined;
|
||||
@@ -74916,29 +74929,9 @@ var ts;
|
||||
return undefined;
|
||||
}
|
||||
var enclosingTextRange = getEnclosingTextRange(targetRange, sourceFile);
|
||||
var _a = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker()), target = _a.target, usagesPerScope = _a.usagesPerScope, errorsPerScope = _a.errorsPerScope;
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
if (requestedChangesIndex !== undefined) {
|
||||
if (errorsPerScope[requestedChangesIndex].length) {
|
||||
return undefined;
|
||||
}
|
||||
return [extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context)];
|
||||
}
|
||||
else {
|
||||
return scopes.map(function (scope, i) {
|
||||
var errors = errorsPerScope[i];
|
||||
if (errors.length) {
|
||||
return {
|
||||
scope: scope,
|
||||
scopeDescription: getDescriptionForScope(scope),
|
||||
errors: errors
|
||||
};
|
||||
}
|
||||
return { scope: scope, scopeDescription: getDescriptionForScope(scope) };
|
||||
});
|
||||
}
|
||||
var readsAndWrites = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker());
|
||||
return { scopes: scopes, readsAndWrites: readsAndWrites };
|
||||
}
|
||||
extractMethod_1.getPossibleExtractions = getPossibleExtractions;
|
||||
function getDescriptionForScope(scope) {
|
||||
if (ts.isFunctionLike(scope)) {
|
||||
switch (scope.kind) {
|
||||
@@ -74960,7 +74953,7 @@ var ts;
|
||||
return "'set " + scope.name.getText() + "'";
|
||||
}
|
||||
}
|
||||
else if (isModuleBlock(scope)) {
|
||||
else if (ts.isModuleBlock(scope)) {
|
||||
return "namespace '" + scope.parent.name.getText() + "'";
|
||||
}
|
||||
else if (ts.isClassLike(scope)) {
|
||||
@@ -74977,14 +74970,10 @@ var ts;
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
function getUniqueName(isNameOkay) {
|
||||
function getUniqueName(fileText) {
|
||||
var functionNameText = "newFunction";
|
||||
if (isNameOkay(functionNameText)) {
|
||||
return functionNameText;
|
||||
}
|
||||
var i = 1;
|
||||
while (!isNameOkay(functionNameText = "newFunction_" + i)) {
|
||||
i++;
|
||||
for (var i = 1; fileText.indexOf(functionNameText) !== -1; i++) {
|
||||
functionNameText = "newFunction_" + i;
|
||||
}
|
||||
return functionNameText;
|
||||
}
|
||||
@@ -74992,10 +74981,9 @@ var ts;
|
||||
var usagesInScope = _a.usages, substitutions = _a.substitutions;
|
||||
var checker = context.program.getTypeChecker();
|
||||
var file = scope.getSourceFile();
|
||||
var functionNameText = getUniqueName(function (n) { return !file.identifiers.has(n); });
|
||||
var functionNameText = getUniqueName(file.text);
|
||||
var isJS = ts.isInJavaScriptFile(scope);
|
||||
var functionName = ts.createIdentifier(functionNameText);
|
||||
var functionReference = ts.createIdentifier(functionNameText);
|
||||
var returnType = undefined;
|
||||
var parameters = [];
|
||||
var callArguments = [];
|
||||
@@ -75018,7 +75006,7 @@ var ts;
|
||||
var contextualType = checker.getContextualType(node);
|
||||
returnType = checker.typeToTypeNode(contextualType);
|
||||
}
|
||||
var _b = transformFunctionBody(node), body = _b.body, returnValueProperty = _b.returnValueProperty;
|
||||
var _b = transformFunctionBody(node, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty;
|
||||
var newFunction;
|
||||
if (ts.isClassLike(scope)) {
|
||||
var modifiers = isJS ? [] : [ts.createToken(112)];
|
||||
@@ -75036,7 +75024,8 @@ var ts;
|
||||
var changeTracker = ts.textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter });
|
||||
var newNodes = [];
|
||||
var call = ts.createCall(ts.isClassLike(scope) ? ts.createPropertyAccess(range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.getText()) : ts.createThis(), functionReference) : functionReference, undefined, callArguments);
|
||||
var called = getCalledExpression(scope, range, functionNameText);
|
||||
var call = ts.createCall(called, undefined, callArguments);
|
||||
if (range.facts & RangeFacts.IsGenerator) {
|
||||
call = ts.createYield(ts.createToken(39), call);
|
||||
}
|
||||
@@ -75086,65 +75075,85 @@ var ts;
|
||||
else {
|
||||
changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes, { nodeSeparator: context.newLineCharacter });
|
||||
}
|
||||
return {
|
||||
scope: scope,
|
||||
scopeDescription: getDescriptionForScope(scope),
|
||||
changes: changeTracker.getChanges()
|
||||
};
|
||||
function getPropertyAssignmentsForWrites(writes) {
|
||||
return writes.map(function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
|
||||
}
|
||||
function generateReturnValueProperty() {
|
||||
return "__return";
|
||||
}
|
||||
function transformFunctionBody(body) {
|
||||
if (ts.isBlock(body) && !writes && substitutions.size === 0) {
|
||||
return { body: ts.createBlock(body.statements, true), returnValueProperty: undefined };
|
||||
}
|
||||
var returnValueProperty;
|
||||
var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
|
||||
if (writes || substitutions.size) {
|
||||
var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
|
||||
if (writes && !(range.facts & RangeFacts.HasReturn) && ts.isStatement(body)) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (assignments.length === 1) {
|
||||
rewrittenStatements.push(ts.createReturn(assignments[0].name));
|
||||
}
|
||||
else {
|
||||
rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
|
||||
}
|
||||
var edits = changeTracker.getChanges();
|
||||
var renameRange = isReadonlyArray(range.range) ? range.range[0] : range.range;
|
||||
var renameFilename = renameRange.getSourceFile().fileName;
|
||||
var renameLocation = getRenameLocation(edits, renameFilename, functionNameText);
|
||||
return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits };
|
||||
}
|
||||
function getRenameLocation(edits, renameFilename, functionNameText) {
|
||||
var delta = 0;
|
||||
for (var _i = 0, edits_1 = edits; _i < edits_1.length; _i++) {
|
||||
var _a = edits_1[_i], fileName = _a.fileName, textChanges_1 = _a.textChanges;
|
||||
ts.Debug.assert(fileName === renameFilename);
|
||||
for (var _b = 0, textChanges_2 = textChanges_1; _b < textChanges_2.length; _b++) {
|
||||
var change = textChanges_2[_b];
|
||||
var span_17 = change.span, newText = change.newText;
|
||||
var index = newText.indexOf(functionNameText);
|
||||
if (index !== -1) {
|
||||
return span_17.start + delta + index;
|
||||
}
|
||||
return { body: ts.createBlock(rewrittenStatements, true), returnValueProperty: returnValueProperty };
|
||||
delta += newText.length - span_17.length;
|
||||
}
|
||||
else {
|
||||
return { body: ts.createBlock(statements, true), returnValueProperty: undefined };
|
||||
}
|
||||
function visitor(node) {
|
||||
if (node.kind === 219 && writes) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (node.expression) {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = generateReturnValueProperty();
|
||||
}
|
||||
assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return ts.createReturn(assignments[0].name);
|
||||
}
|
||||
else {
|
||||
return ts.createReturn(ts.createObjectLiteral(assignments));
|
||||
}
|
||||
}
|
||||
throw new Error();
|
||||
}
|
||||
function getCalledExpression(scope, range, functionNameText) {
|
||||
var functionReference = ts.createIdentifier(functionNameText);
|
||||
if (ts.isClassLike(scope)) {
|
||||
var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis();
|
||||
return ts.createPropertyAccess(lhs, functionReference);
|
||||
}
|
||||
else {
|
||||
return functionReference;
|
||||
}
|
||||
}
|
||||
function transformFunctionBody(body, writes, substitutions, hasReturn) {
|
||||
if (ts.isBlock(body) && !writes && substitutions.size === 0) {
|
||||
return { body: ts.createBlock(body.statements, true), returnValueProperty: undefined };
|
||||
}
|
||||
var returnValueProperty;
|
||||
var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
|
||||
if (writes || substitutions.size) {
|
||||
var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
|
||||
if (writes && !hasReturn && ts.isStatement(body)) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (assignments.length === 1) {
|
||||
rewrittenStatements.push(ts.createReturn(assignments[0].name));
|
||||
}
|
||||
else {
|
||||
var substitution = substitutions.get(ts.getNodeId(node).toString());
|
||||
return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext);
|
||||
rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
|
||||
}
|
||||
}
|
||||
return { body: ts.createBlock(rewrittenStatements, true), returnValueProperty: returnValueProperty };
|
||||
}
|
||||
else {
|
||||
return { body: ts.createBlock(statements, true), returnValueProperty: undefined };
|
||||
}
|
||||
function visitor(node) {
|
||||
if (node.kind === 219 && writes) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (node.expression) {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = "__return";
|
||||
}
|
||||
assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return ts.createReturn(assignments[0].name);
|
||||
}
|
||||
else {
|
||||
return ts.createReturn(ts.createObjectLiteral(assignments));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var substitution = substitutions.get(ts.getNodeId(node).toString());
|
||||
return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
extractMethod_1.extractFunctionInScope = extractFunctionInScope;
|
||||
function isModuleBlock(n) {
|
||||
return n.kind === 234;
|
||||
function getPropertyAssignmentsForWrites(writes) {
|
||||
return writes.map(function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
|
||||
}
|
||||
function isReadonlyArray(v) {
|
||||
return ts.isArray(v);
|
||||
@@ -81209,8 +81218,8 @@ var ts;
|
||||
{ start: start, end: end, text: text, code: code, category: category, source: source };
|
||||
}
|
||||
function allEditsBeforePos(edits, pos) {
|
||||
for (var _i = 0, edits_1 = edits; _i < edits_1.length; _i++) {
|
||||
var edit = edits_1[_i];
|
||||
for (var _i = 0, edits_2 = edits; _i < edits_2.length; _i++) {
|
||||
var edit = edits_2[_i];
|
||||
if (ts.textSpanEnd(edit.span) >= pos) {
|
||||
return false;
|
||||
}
|
||||
@@ -82372,12 +82381,12 @@ var ts;
|
||||
return undefined;
|
||||
}
|
||||
if (simplifiedResult) {
|
||||
var span_17 = helpItems.applicableSpan;
|
||||
var span_18 = helpItems.applicableSpan;
|
||||
return {
|
||||
items: helpItems.items,
|
||||
applicableSpan: {
|
||||
start: scriptInfo.positionToLineOffset(span_17.start),
|
||||
end: scriptInfo.positionToLineOffset(span_17.start + span_17.length)
|
||||
start: scriptInfo.positionToLineOffset(span_18.start),
|
||||
end: scriptInfo.positionToLineOffset(span_18.start + span_18.length)
|
||||
},
|
||||
selectedItemIndex: helpItems.selectedItemIndex,
|
||||
argumentIndex: helpItems.argumentIndex,
|
||||
|
||||
Vendored
+2
-2
@@ -3283,8 +3283,8 @@ declare namespace ts {
|
||||
};
|
||||
type RefactorEditInfo = {
|
||||
edits: FileTextChanges[];
|
||||
renameFilename?: string;
|
||||
renameLocation?: number;
|
||||
renameFilename: string | undefined;
|
||||
renameLocation: number | undefined;
|
||||
};
|
||||
interface TextInsertion {
|
||||
newText: string;
|
||||
|
||||
+115
-106
@@ -12155,7 +12155,8 @@ var ts;
|
||||
return token() === 24 ||
|
||||
isIdentifierOrPattern() ||
|
||||
ts.isModifierKind(token()) ||
|
||||
token() === 57 || isStartOfType();
|
||||
token() === 57 ||
|
||||
isStartOfType(true);
|
||||
}
|
||||
function parseParameter() {
|
||||
var node = createNode(146);
|
||||
@@ -12494,7 +12495,7 @@ var ts;
|
||||
return parseTypeReference();
|
||||
}
|
||||
}
|
||||
function isStartOfType() {
|
||||
function isStartOfType(inStartOfParameter) {
|
||||
switch (token()) {
|
||||
case 119:
|
||||
case 136:
|
||||
@@ -12521,9 +12522,9 @@ var ts;
|
||||
case 39:
|
||||
return true;
|
||||
case 38:
|
||||
return lookAhead(nextTokenIsNumericLiteral);
|
||||
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
|
||||
case 19:
|
||||
return lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
@@ -74425,7 +74426,9 @@ var ts;
|
||||
deleteCallback();
|
||||
}
|
||||
return {
|
||||
edits: changeTracker.getChanges()
|
||||
edits: changeTracker.getChanges(),
|
||||
renameFilename: undefined,
|
||||
renameLocation: undefined,
|
||||
};
|
||||
function deleteNode(node, inList) {
|
||||
if (inList === void 0) { inList = false; }
|
||||
@@ -74576,11 +74579,11 @@ var ts;
|
||||
var usedNames = ts.createMap();
|
||||
var i = 0;
|
||||
for (var _i = 0, extractions_1 = extractions; _i < extractions_1.length; _i++) {
|
||||
var extr = extractions_1[_i];
|
||||
if (extr.errors && extr.errors.length) {
|
||||
var _a = extractions_1[_i], scopeDescription = _a.scopeDescription, errors = _a.errors;
|
||||
if (errors.length) {
|
||||
continue;
|
||||
}
|
||||
var description = ts.formatStringFromArgs(ts.Diagnostics.Extract_function_into_0.message, [extr.scopeDescription]);
|
||||
var description = ts.formatStringFromArgs(ts.Diagnostics.Extract_function_into_0.message, [scopeDescription]);
|
||||
if (!usedNames.has(description)) {
|
||||
usedNames.set(description, true);
|
||||
actions.push({
|
||||
@@ -74608,9 +74611,7 @@ var ts;
|
||||
ts.Debug.assert(!!parsedIndexMatch, "Scope name should have matched the regexp");
|
||||
var index = +parsedIndexMatch[1];
|
||||
ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the scope index");
|
||||
var extractions = getPossibleExtractions(targetRange, context, index);
|
||||
ts.Debug.assert(extractions !== undefined, "The extraction went missing? How?");
|
||||
return ({ edits: extractions[0].changes });
|
||||
return getExtractionAtIndex(targetRange, context, index);
|
||||
}
|
||||
var Messages;
|
||||
(function (Messages) {
|
||||
@@ -74639,7 +74640,7 @@ var ts;
|
||||
RangeFacts[RangeFacts["IsAsyncFunction"] = 4] = "IsAsyncFunction";
|
||||
RangeFacts[RangeFacts["UsesThis"] = 8] = "UsesThis";
|
||||
RangeFacts[RangeFacts["InStaticRegion"] = 16] = "InStaticRegion";
|
||||
})(RangeFacts = extractMethod_1.RangeFacts || (extractMethod_1.RangeFacts = {}));
|
||||
})(RangeFacts || (RangeFacts = {}));
|
||||
function getRangeToExtract(sourceFile, span) {
|
||||
var length = span.length || 0;
|
||||
var start = getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, false), sourceFile, span);
|
||||
@@ -74879,7 +74880,7 @@ var ts;
|
||||
return undefined;
|
||||
}
|
||||
function isValidExtractionTarget(node) {
|
||||
return (node.kind === 228) || ts.isSourceFile(node) || isModuleBlock(node) || ts.isClassLike(node);
|
||||
return (node.kind === 228) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node);
|
||||
}
|
||||
function collectEnclosingScopes(range) {
|
||||
var current = isReadonlyArray(range.range) ? ts.firstOrUndefined(range.range) : range.range;
|
||||
@@ -74904,9 +74905,21 @@ var ts;
|
||||
}
|
||||
return scopes;
|
||||
}
|
||||
extractMethod_1.collectEnclosingScopes = collectEnclosingScopes;
|
||||
function getPossibleExtractions(targetRange, context, requestedChangesIndex) {
|
||||
if (requestedChangesIndex === void 0) { requestedChangesIndex = undefined; }
|
||||
function getExtractionAtIndex(targetRange, context, requestedChangesIndex) {
|
||||
var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, errorsPerScope = _b.errorsPerScope;
|
||||
ts.Debug.assert(!errorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context);
|
||||
}
|
||||
extractMethod_1.getExtractionAtIndex = getExtractionAtIndex;
|
||||
function getPossibleExtractions(targetRange, context) {
|
||||
var extractions = getPossibleExtractionsWorker(targetRange, context);
|
||||
return extractions && extractions.scopes.map(function (scope, i) {
|
||||
return ({ scopeDescription: getDescriptionForScope(scope), errors: extractions.readsAndWrites.errorsPerScope[i] });
|
||||
});
|
||||
}
|
||||
extractMethod_1.getPossibleExtractions = getPossibleExtractions;
|
||||
function getPossibleExtractionsWorker(targetRange, context) {
|
||||
var sourceFile = context.file;
|
||||
if (targetRange === undefined) {
|
||||
return undefined;
|
||||
@@ -74916,29 +74929,9 @@ var ts;
|
||||
return undefined;
|
||||
}
|
||||
var enclosingTextRange = getEnclosingTextRange(targetRange, sourceFile);
|
||||
var _a = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker()), target = _a.target, usagesPerScope = _a.usagesPerScope, errorsPerScope = _a.errorsPerScope;
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
if (requestedChangesIndex !== undefined) {
|
||||
if (errorsPerScope[requestedChangesIndex].length) {
|
||||
return undefined;
|
||||
}
|
||||
return [extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context)];
|
||||
}
|
||||
else {
|
||||
return scopes.map(function (scope, i) {
|
||||
var errors = errorsPerScope[i];
|
||||
if (errors.length) {
|
||||
return {
|
||||
scope: scope,
|
||||
scopeDescription: getDescriptionForScope(scope),
|
||||
errors: errors
|
||||
};
|
||||
}
|
||||
return { scope: scope, scopeDescription: getDescriptionForScope(scope) };
|
||||
});
|
||||
}
|
||||
var readsAndWrites = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker());
|
||||
return { scopes: scopes, readsAndWrites: readsAndWrites };
|
||||
}
|
||||
extractMethod_1.getPossibleExtractions = getPossibleExtractions;
|
||||
function getDescriptionForScope(scope) {
|
||||
if (ts.isFunctionLike(scope)) {
|
||||
switch (scope.kind) {
|
||||
@@ -74960,7 +74953,7 @@ var ts;
|
||||
return "'set " + scope.name.getText() + "'";
|
||||
}
|
||||
}
|
||||
else if (isModuleBlock(scope)) {
|
||||
else if (ts.isModuleBlock(scope)) {
|
||||
return "namespace '" + scope.parent.name.getText() + "'";
|
||||
}
|
||||
else if (ts.isClassLike(scope)) {
|
||||
@@ -74977,14 +74970,10 @@ var ts;
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
function getUniqueName(isNameOkay) {
|
||||
function getUniqueName(fileText) {
|
||||
var functionNameText = "newFunction";
|
||||
if (isNameOkay(functionNameText)) {
|
||||
return functionNameText;
|
||||
}
|
||||
var i = 1;
|
||||
while (!isNameOkay(functionNameText = "newFunction_" + i)) {
|
||||
i++;
|
||||
for (var i = 1; fileText.indexOf(functionNameText) !== -1; i++) {
|
||||
functionNameText = "newFunction_" + i;
|
||||
}
|
||||
return functionNameText;
|
||||
}
|
||||
@@ -74992,10 +74981,9 @@ var ts;
|
||||
var usagesInScope = _a.usages, substitutions = _a.substitutions;
|
||||
var checker = context.program.getTypeChecker();
|
||||
var file = scope.getSourceFile();
|
||||
var functionNameText = getUniqueName(function (n) { return !file.identifiers.has(n); });
|
||||
var functionNameText = getUniqueName(file.text);
|
||||
var isJS = ts.isInJavaScriptFile(scope);
|
||||
var functionName = ts.createIdentifier(functionNameText);
|
||||
var functionReference = ts.createIdentifier(functionNameText);
|
||||
var returnType = undefined;
|
||||
var parameters = [];
|
||||
var callArguments = [];
|
||||
@@ -75018,7 +75006,7 @@ var ts;
|
||||
var contextualType = checker.getContextualType(node);
|
||||
returnType = checker.typeToTypeNode(contextualType);
|
||||
}
|
||||
var _b = transformFunctionBody(node), body = _b.body, returnValueProperty = _b.returnValueProperty;
|
||||
var _b = transformFunctionBody(node, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty;
|
||||
var newFunction;
|
||||
if (ts.isClassLike(scope)) {
|
||||
var modifiers = isJS ? [] : [ts.createToken(112)];
|
||||
@@ -75036,7 +75024,8 @@ var ts;
|
||||
var changeTracker = ts.textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter });
|
||||
var newNodes = [];
|
||||
var call = ts.createCall(ts.isClassLike(scope) ? ts.createPropertyAccess(range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.getText()) : ts.createThis(), functionReference) : functionReference, undefined, callArguments);
|
||||
var called = getCalledExpression(scope, range, functionNameText);
|
||||
var call = ts.createCall(called, undefined, callArguments);
|
||||
if (range.facts & RangeFacts.IsGenerator) {
|
||||
call = ts.createYield(ts.createToken(39), call);
|
||||
}
|
||||
@@ -75086,65 +75075,85 @@ var ts;
|
||||
else {
|
||||
changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes, { nodeSeparator: context.newLineCharacter });
|
||||
}
|
||||
return {
|
||||
scope: scope,
|
||||
scopeDescription: getDescriptionForScope(scope),
|
||||
changes: changeTracker.getChanges()
|
||||
};
|
||||
function getPropertyAssignmentsForWrites(writes) {
|
||||
return writes.map(function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
|
||||
}
|
||||
function generateReturnValueProperty() {
|
||||
return "__return";
|
||||
}
|
||||
function transformFunctionBody(body) {
|
||||
if (ts.isBlock(body) && !writes && substitutions.size === 0) {
|
||||
return { body: ts.createBlock(body.statements, true), returnValueProperty: undefined };
|
||||
}
|
||||
var returnValueProperty;
|
||||
var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
|
||||
if (writes || substitutions.size) {
|
||||
var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
|
||||
if (writes && !(range.facts & RangeFacts.HasReturn) && ts.isStatement(body)) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (assignments.length === 1) {
|
||||
rewrittenStatements.push(ts.createReturn(assignments[0].name));
|
||||
}
|
||||
else {
|
||||
rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
|
||||
}
|
||||
var edits = changeTracker.getChanges();
|
||||
var renameRange = isReadonlyArray(range.range) ? range.range[0] : range.range;
|
||||
var renameFilename = renameRange.getSourceFile().fileName;
|
||||
var renameLocation = getRenameLocation(edits, renameFilename, functionNameText);
|
||||
return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits };
|
||||
}
|
||||
function getRenameLocation(edits, renameFilename, functionNameText) {
|
||||
var delta = 0;
|
||||
for (var _i = 0, edits_1 = edits; _i < edits_1.length; _i++) {
|
||||
var _a = edits_1[_i], fileName = _a.fileName, textChanges_1 = _a.textChanges;
|
||||
ts.Debug.assert(fileName === renameFilename);
|
||||
for (var _b = 0, textChanges_2 = textChanges_1; _b < textChanges_2.length; _b++) {
|
||||
var change = textChanges_2[_b];
|
||||
var span_17 = change.span, newText = change.newText;
|
||||
var index = newText.indexOf(functionNameText);
|
||||
if (index !== -1) {
|
||||
return span_17.start + delta + index;
|
||||
}
|
||||
return { body: ts.createBlock(rewrittenStatements, true), returnValueProperty: returnValueProperty };
|
||||
delta += newText.length - span_17.length;
|
||||
}
|
||||
else {
|
||||
return { body: ts.createBlock(statements, true), returnValueProperty: undefined };
|
||||
}
|
||||
function visitor(node) {
|
||||
if (node.kind === 219 && writes) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (node.expression) {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = generateReturnValueProperty();
|
||||
}
|
||||
assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return ts.createReturn(assignments[0].name);
|
||||
}
|
||||
else {
|
||||
return ts.createReturn(ts.createObjectLiteral(assignments));
|
||||
}
|
||||
}
|
||||
throw new Error();
|
||||
}
|
||||
function getCalledExpression(scope, range, functionNameText) {
|
||||
var functionReference = ts.createIdentifier(functionNameText);
|
||||
if (ts.isClassLike(scope)) {
|
||||
var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis();
|
||||
return ts.createPropertyAccess(lhs, functionReference);
|
||||
}
|
||||
else {
|
||||
return functionReference;
|
||||
}
|
||||
}
|
||||
function transformFunctionBody(body, writes, substitutions, hasReturn) {
|
||||
if (ts.isBlock(body) && !writes && substitutions.size === 0) {
|
||||
return { body: ts.createBlock(body.statements, true), returnValueProperty: undefined };
|
||||
}
|
||||
var returnValueProperty;
|
||||
var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
|
||||
if (writes || substitutions.size) {
|
||||
var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
|
||||
if (writes && !hasReturn && ts.isStatement(body)) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (assignments.length === 1) {
|
||||
rewrittenStatements.push(ts.createReturn(assignments[0].name));
|
||||
}
|
||||
else {
|
||||
var substitution = substitutions.get(ts.getNodeId(node).toString());
|
||||
return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext);
|
||||
rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
|
||||
}
|
||||
}
|
||||
return { body: ts.createBlock(rewrittenStatements, true), returnValueProperty: returnValueProperty };
|
||||
}
|
||||
else {
|
||||
return { body: ts.createBlock(statements, true), returnValueProperty: undefined };
|
||||
}
|
||||
function visitor(node) {
|
||||
if (node.kind === 219 && writes) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (node.expression) {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = "__return";
|
||||
}
|
||||
assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return ts.createReturn(assignments[0].name);
|
||||
}
|
||||
else {
|
||||
return ts.createReturn(ts.createObjectLiteral(assignments));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var substitution = substitutions.get(ts.getNodeId(node).toString());
|
||||
return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
extractMethod_1.extractFunctionInScope = extractFunctionInScope;
|
||||
function isModuleBlock(n) {
|
||||
return n.kind === 234;
|
||||
function getPropertyAssignmentsForWrites(writes) {
|
||||
return writes.map(function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
|
||||
}
|
||||
function isReadonlyArray(v) {
|
||||
return ts.isArray(v);
|
||||
@@ -77374,8 +77383,8 @@ var ts;
|
||||
{ start: start, end: end, text: text, code: code, category: category, source: source };
|
||||
}
|
||||
function allEditsBeforePos(edits, pos) {
|
||||
for (var _i = 0, edits_1 = edits; _i < edits_1.length; _i++) {
|
||||
var edit = edits_1[_i];
|
||||
for (var _i = 0, edits_2 = edits; _i < edits_2.length; _i++) {
|
||||
var edit = edits_2[_i];
|
||||
if (ts.textSpanEnd(edit.span) >= pos) {
|
||||
return false;
|
||||
}
|
||||
@@ -78537,12 +78546,12 @@ var ts;
|
||||
return undefined;
|
||||
}
|
||||
if (simplifiedResult) {
|
||||
var span_17 = helpItems.applicableSpan;
|
||||
var span_18 = helpItems.applicableSpan;
|
||||
return {
|
||||
items: helpItems.items,
|
||||
applicableSpan: {
|
||||
start: scriptInfo.positionToLineOffset(span_17.start),
|
||||
end: scriptInfo.positionToLineOffset(span_17.start + span_17.length)
|
||||
start: scriptInfo.positionToLineOffset(span_18.start),
|
||||
end: scriptInfo.positionToLineOffset(span_18.start + span_18.length)
|
||||
},
|
||||
selectedItemIndex: helpItems.selectedItemIndex,
|
||||
argumentIndex: helpItems.argumentIndex,
|
||||
|
||||
Vendored
+2
-2
@@ -3935,8 +3935,8 @@ declare namespace ts {
|
||||
*/
|
||||
type RefactorEditInfo = {
|
||||
edits: FileTextChanges[];
|
||||
renameFilename?: string;
|
||||
renameLocation?: number;
|
||||
renameFilename: string | undefined;
|
||||
renameLocation: number | undefined;
|
||||
};
|
||||
interface TextInsertion {
|
||||
newText: string;
|
||||
|
||||
+125
-106
@@ -13845,7 +13845,8 @@ var ts;
|
||||
return token() === 24 /* DotDotDotToken */ ||
|
||||
isIdentifierOrPattern() ||
|
||||
ts.isModifierKind(token()) ||
|
||||
token() === 57 /* AtToken */ || isStartOfType();
|
||||
token() === 57 /* AtToken */ ||
|
||||
isStartOfType(/*inStartOfParameter*/ true);
|
||||
}
|
||||
function parseParameter() {
|
||||
var node = createNode(146 /* Parameter */);
|
||||
@@ -14252,7 +14253,7 @@ var ts;
|
||||
return parseTypeReference();
|
||||
}
|
||||
}
|
||||
function isStartOfType() {
|
||||
function isStartOfType(inStartOfParameter) {
|
||||
switch (token()) {
|
||||
case 119 /* AnyKeyword */:
|
||||
case 136 /* StringKeyword */:
|
||||
@@ -14279,11 +14280,11 @@ var ts;
|
||||
case 39 /* AsteriskToken */:
|
||||
return true;
|
||||
case 38 /* MinusToken */:
|
||||
return lookAhead(nextTokenIsNumericLiteral);
|
||||
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
|
||||
case 19 /* OpenParenToken */:
|
||||
// Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
|
||||
// or something that starts a type. We don't want to consider things like '(1)' a type.
|
||||
return lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
@@ -89385,7 +89386,9 @@ var ts;
|
||||
deleteCallback();
|
||||
}
|
||||
return {
|
||||
edits: changeTracker.getChanges()
|
||||
edits: changeTracker.getChanges(),
|
||||
renameFilename: undefined,
|
||||
renameLocation: undefined,
|
||||
};
|
||||
function deleteNode(node, inList) {
|
||||
if (inList === void 0) { inList = false; }
|
||||
@@ -89561,15 +89564,15 @@ var ts;
|
||||
var usedNames = ts.createMap();
|
||||
var i = 0;
|
||||
for (var _i = 0, extractions_1 = extractions; _i < extractions_1.length; _i++) {
|
||||
var extr = extractions_1[_i];
|
||||
var _a = extractions_1[_i], scopeDescription = _a.scopeDescription, errors = _a.errors;
|
||||
// Skip these since we don't have a way to report errors yet
|
||||
if (extr.errors && extr.errors.length) {
|
||||
if (errors.length) {
|
||||
continue;
|
||||
}
|
||||
// Don't issue refactorings with duplicated names.
|
||||
// Scopes come back in "innermost first" order, so extractions will
|
||||
// preferentially go into nearer scopes
|
||||
var description = ts.formatStringFromArgs(ts.Diagnostics.Extract_function_into_0.message, [extr.scopeDescription]);
|
||||
var description = ts.formatStringFromArgs(ts.Diagnostics.Extract_function_into_0.message, [scopeDescription]);
|
||||
if (!usedNames.has(description)) {
|
||||
usedNames.set(description, true);
|
||||
actions.push({
|
||||
@@ -89599,10 +89602,7 @@ var ts;
|
||||
ts.Debug.assert(!!parsedIndexMatch, "Scope name should have matched the regexp");
|
||||
var index = +parsedIndexMatch[1];
|
||||
ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the scope index");
|
||||
var extractions = getPossibleExtractions(targetRange, context, index);
|
||||
// Scope is no longer valid from when the user issued the refactor (??)
|
||||
ts.Debug.assert(extractions !== undefined, "The extraction went missing? How?");
|
||||
return ({ edits: extractions[0].changes });
|
||||
return getExtractionAtIndex(targetRange, context, index);
|
||||
}
|
||||
// Move these into diagnostic messages if they become user-facing
|
||||
var Messages;
|
||||
@@ -89635,13 +89635,14 @@ var ts;
|
||||
* The range is in a function which needs the 'static' modifier in a class
|
||||
*/
|
||||
RangeFacts[RangeFacts["InStaticRegion"] = 16] = "InStaticRegion";
|
||||
})(RangeFacts = extractMethod_1.RangeFacts || (extractMethod_1.RangeFacts = {}));
|
||||
})(RangeFacts || (RangeFacts = {}));
|
||||
/**
|
||||
* getRangeToExtract takes a span inside a text file and returns either an expression or an array
|
||||
* of statements representing the minimum set of nodes needed to extract the entire span. This
|
||||
* process may fail, in which case a set of errors is returned instead (these are currently
|
||||
* not shown to the user, but can be used by us diagnostically)
|
||||
*/
|
||||
// exported only for tests
|
||||
function getRangeToExtract(sourceFile, span) {
|
||||
var length = span.length || 0;
|
||||
// Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span.
|
||||
@@ -89927,7 +89928,7 @@ var ts;
|
||||
}
|
||||
function isValidExtractionTarget(node) {
|
||||
// Note that we don't use isFunctionLike because we don't want to put the extracted closure *inside* a method
|
||||
return (node.kind === 228 /* FunctionDeclaration */) || ts.isSourceFile(node) || isModuleBlock(node) || ts.isClassLike(node);
|
||||
return (node.kind === 228 /* FunctionDeclaration */) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node);
|
||||
}
|
||||
/**
|
||||
* Computes possible places we could extract the function into. For example,
|
||||
@@ -89965,14 +89966,29 @@ var ts;
|
||||
}
|
||||
return scopes;
|
||||
}
|
||||
extractMethod_1.collectEnclosingScopes = collectEnclosingScopes;
|
||||
// exported only for tests
|
||||
function getExtractionAtIndex(targetRange, context, requestedChangesIndex) {
|
||||
var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, errorsPerScope = _b.errorsPerScope;
|
||||
ts.Debug.assert(!errorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context);
|
||||
}
|
||||
extractMethod_1.getExtractionAtIndex = getExtractionAtIndex;
|
||||
/**
|
||||
* Given a piece of text to extract ('targetRange'), computes a list of possible extractions.
|
||||
* Each returned ExtractResultForScope corresponds to a possible target scope and is either a set of changes
|
||||
* or an error explaining why we can't extract into that scope.
|
||||
*/
|
||||
function getPossibleExtractions(targetRange, context, requestedChangesIndex) {
|
||||
if (requestedChangesIndex === void 0) { requestedChangesIndex = undefined; }
|
||||
// exported only for tests
|
||||
function getPossibleExtractions(targetRange, context) {
|
||||
var extractions = getPossibleExtractionsWorker(targetRange, context);
|
||||
// Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547
|
||||
return extractions && extractions.scopes.map(function (scope, i) {
|
||||
return ({ scopeDescription: getDescriptionForScope(scope), errors: extractions.readsAndWrites.errorsPerScope[i] });
|
||||
});
|
||||
}
|
||||
extractMethod_1.getPossibleExtractions = getPossibleExtractions;
|
||||
function getPossibleExtractionsWorker(targetRange, context) {
|
||||
var sourceFile = context.file;
|
||||
if (targetRange === undefined) {
|
||||
return undefined;
|
||||
@@ -89982,29 +89998,9 @@ var ts;
|
||||
return undefined;
|
||||
}
|
||||
var enclosingTextRange = getEnclosingTextRange(targetRange, sourceFile);
|
||||
var _a = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker()), target = _a.target, usagesPerScope = _a.usagesPerScope, errorsPerScope = _a.errorsPerScope;
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
if (requestedChangesIndex !== undefined) {
|
||||
if (errorsPerScope[requestedChangesIndex].length) {
|
||||
return undefined;
|
||||
}
|
||||
return [extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context)];
|
||||
}
|
||||
else {
|
||||
return scopes.map(function (scope, i) {
|
||||
var errors = errorsPerScope[i];
|
||||
if (errors.length) {
|
||||
return {
|
||||
scope: scope,
|
||||
scopeDescription: getDescriptionForScope(scope),
|
||||
errors: errors
|
||||
};
|
||||
}
|
||||
return { scope: scope, scopeDescription: getDescriptionForScope(scope) };
|
||||
});
|
||||
}
|
||||
var readsAndWrites = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker());
|
||||
return { scopes: scopes, readsAndWrites: readsAndWrites };
|
||||
}
|
||||
extractMethod_1.getPossibleExtractions = getPossibleExtractions;
|
||||
function getDescriptionForScope(scope) {
|
||||
if (ts.isFunctionLike(scope)) {
|
||||
switch (scope.kind) {
|
||||
@@ -90026,7 +90022,7 @@ var ts;
|
||||
return "'set " + scope.name.getText() + "'";
|
||||
}
|
||||
}
|
||||
else if (isModuleBlock(scope)) {
|
||||
else if (ts.isModuleBlock(scope)) {
|
||||
return "namespace '" + scope.parent.name.getText() + "'";
|
||||
}
|
||||
else if (ts.isClassLike(scope)) {
|
||||
@@ -90043,26 +90039,25 @@ var ts;
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
function getUniqueName(isNameOkay) {
|
||||
function getUniqueName(fileText) {
|
||||
var functionNameText = "newFunction";
|
||||
if (isNameOkay(functionNameText)) {
|
||||
return functionNameText;
|
||||
}
|
||||
var i = 1;
|
||||
while (!isNameOkay(functionNameText = "newFunction_" + i)) {
|
||||
i++;
|
||||
for (var i = 1; fileText.indexOf(functionNameText) !== -1; i++) {
|
||||
functionNameText = "newFunction_" + i;
|
||||
}
|
||||
return functionNameText;
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
function extractFunctionInScope(node, scope, _a, range, context) {
|
||||
var usagesInScope = _a.usages, substitutions = _a.substitutions;
|
||||
var checker = context.program.getTypeChecker();
|
||||
// Make a unique name for the extracted function
|
||||
var file = scope.getSourceFile();
|
||||
var functionNameText = getUniqueName(function (n) { return !file.identifiers.has(n); });
|
||||
var functionNameText = getUniqueName(file.text);
|
||||
var isJS = ts.isInJavaScriptFile(scope);
|
||||
var functionName = ts.createIdentifier(functionNameText);
|
||||
var functionReference = ts.createIdentifier(functionNameText);
|
||||
var returnType = undefined;
|
||||
var parameters = [];
|
||||
var callArguments = [];
|
||||
@@ -90093,7 +90088,7 @@ var ts;
|
||||
var contextualType = checker.getContextualType(node);
|
||||
returnType = checker.typeToTypeNode(contextualType);
|
||||
}
|
||||
var _b = transformFunctionBody(node), body = _b.body, returnValueProperty = _b.returnValueProperty;
|
||||
var _b = transformFunctionBody(node, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty;
|
||||
var newFunction;
|
||||
if (ts.isClassLike(scope)) {
|
||||
// always create private method in TypeScript files
|
||||
@@ -90119,7 +90114,8 @@ var ts;
|
||||
changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter });
|
||||
var newNodes = [];
|
||||
// replace range with function call
|
||||
var call = ts.createCall(ts.isClassLike(scope) ? ts.createPropertyAccess(range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.getText()) : ts.createThis(), functionReference) : functionReference,
|
||||
var called = getCalledExpression(scope, range, functionNameText);
|
||||
var call = ts.createCall(called,
|
||||
/*typeArguments*/ undefined, callArguments);
|
||||
if (range.facts & RangeFacts.IsGenerator) {
|
||||
call = ts.createYield(ts.createToken(39 /* AsteriskToken */), call);
|
||||
@@ -90176,69 +90172,92 @@ var ts;
|
||||
else {
|
||||
changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes, { nodeSeparator: context.newLineCharacter });
|
||||
}
|
||||
return {
|
||||
scope: scope,
|
||||
scopeDescription: getDescriptionForScope(scope),
|
||||
changes: changeTracker.getChanges()
|
||||
};
|
||||
function getPropertyAssignmentsForWrites(writes) {
|
||||
return writes.map(function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
|
||||
}
|
||||
function generateReturnValueProperty() {
|
||||
return "__return";
|
||||
}
|
||||
function transformFunctionBody(body) {
|
||||
if (ts.isBlock(body) && !writes && substitutions.size === 0) {
|
||||
// already block, no writes to propagate back, no substitutions - can use node as is
|
||||
return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
var returnValueProperty;
|
||||
var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
|
||||
// rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
|
||||
if (writes || substitutions.size) {
|
||||
var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
|
||||
if (writes && !(range.facts & RangeFacts.HasReturn) && ts.isStatement(body)) {
|
||||
// add return at the end to propagate writes back in case if control flow falls out of the function body
|
||||
// it is ok to know that range has at least one return since it we only allow unconditional returns
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (assignments.length === 1) {
|
||||
rewrittenStatements.push(ts.createReturn(assignments[0].name));
|
||||
}
|
||||
else {
|
||||
rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
|
||||
}
|
||||
var edits = changeTracker.getChanges();
|
||||
var renameRange = isReadonlyArray(range.range) ? range.range[0] : range.range;
|
||||
var renameFilename = renameRange.getSourceFile().fileName;
|
||||
var renameLocation = getRenameLocation(edits, renameFilename, functionNameText);
|
||||
return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits };
|
||||
}
|
||||
function getRenameLocation(edits, renameFilename, functionNameText) {
|
||||
var delta = 0;
|
||||
for (var _i = 0, edits_1 = edits; _i < edits_1.length; _i++) {
|
||||
var _a = edits_1[_i], fileName = _a.fileName, textChanges_1 = _a.textChanges;
|
||||
ts.Debug.assert(fileName === renameFilename);
|
||||
for (var _b = 0, textChanges_2 = textChanges_1; _b < textChanges_2.length; _b++) {
|
||||
var change = textChanges_2[_b];
|
||||
var span_17 = change.span, newText = change.newText;
|
||||
// TODO(acasey): We are assuming that the call expression comes before the function declaration,
|
||||
// because we want the new cursor to be on the call expression,
|
||||
// which is closer to where the user was before extracting the function.
|
||||
var index = newText.indexOf(functionNameText);
|
||||
if (index !== -1) {
|
||||
return span_17.start + delta + index;
|
||||
}
|
||||
return { body: ts.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty: returnValueProperty };
|
||||
delta += newText.length - span_17.length;
|
||||
}
|
||||
else {
|
||||
return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
function visitor(node) {
|
||||
if (node.kind === 219 /* ReturnStatement */ && writes) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (node.expression) {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = generateReturnValueProperty();
|
||||
}
|
||||
assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return ts.createReturn(assignments[0].name);
|
||||
}
|
||||
else {
|
||||
return ts.createReturn(ts.createObjectLiteral(assignments));
|
||||
}
|
||||
}
|
||||
throw new Error(); // Didn't find the text we inserted?
|
||||
}
|
||||
function getCalledExpression(scope, range, functionNameText) {
|
||||
var functionReference = ts.createIdentifier(functionNameText);
|
||||
if (ts.isClassLike(scope)) {
|
||||
var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis();
|
||||
return ts.createPropertyAccess(lhs, functionReference);
|
||||
}
|
||||
else {
|
||||
return functionReference;
|
||||
}
|
||||
}
|
||||
function transformFunctionBody(body, writes, substitutions, hasReturn) {
|
||||
if (ts.isBlock(body) && !writes && substitutions.size === 0) {
|
||||
// already block, no writes to propagate back, no substitutions - can use node as is
|
||||
return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
var returnValueProperty;
|
||||
var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
|
||||
// rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
|
||||
if (writes || substitutions.size) {
|
||||
var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
|
||||
if (writes && !hasReturn && ts.isStatement(body)) {
|
||||
// add return at the end to propagate writes back in case if control flow falls out of the function body
|
||||
// it is ok to know that range has at least one return since it we only allow unconditional returns
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (assignments.length === 1) {
|
||||
rewrittenStatements.push(ts.createReturn(assignments[0].name));
|
||||
}
|
||||
else {
|
||||
var substitution = substitutions.get(ts.getNodeId(node).toString());
|
||||
return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext);
|
||||
rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
|
||||
}
|
||||
}
|
||||
return { body: ts.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty: returnValueProperty };
|
||||
}
|
||||
else {
|
||||
return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
function visitor(node) {
|
||||
if (node.kind === 219 /* ReturnStatement */ && writes) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (node.expression) {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = "__return";
|
||||
}
|
||||
assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return ts.createReturn(assignments[0].name);
|
||||
}
|
||||
else {
|
||||
return ts.createReturn(ts.createObjectLiteral(assignments));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var substitution = substitutions.get(ts.getNodeId(node).toString());
|
||||
return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
extractMethod_1.extractFunctionInScope = extractFunctionInScope;
|
||||
function isModuleBlock(n) {
|
||||
return n.kind === 234 /* ModuleBlock */;
|
||||
function getPropertyAssignmentsForWrites(writes) {
|
||||
return writes.map(function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
|
||||
}
|
||||
function isReadonlyArray(v) {
|
||||
return ts.isArray(v);
|
||||
|
||||
Vendored
+2
-2
@@ -3935,8 +3935,8 @@ declare namespace ts {
|
||||
*/
|
||||
type RefactorEditInfo = {
|
||||
edits: FileTextChanges[];
|
||||
renameFilename?: string;
|
||||
renameLocation?: number;
|
||||
renameFilename: string | undefined;
|
||||
renameLocation: number | undefined;
|
||||
};
|
||||
interface TextInsertion {
|
||||
newText: string;
|
||||
|
||||
+125
-106
@@ -13845,7 +13845,8 @@ var ts;
|
||||
return token() === 24 /* DotDotDotToken */ ||
|
||||
isIdentifierOrPattern() ||
|
||||
ts.isModifierKind(token()) ||
|
||||
token() === 57 /* AtToken */ || isStartOfType();
|
||||
token() === 57 /* AtToken */ ||
|
||||
isStartOfType(/*inStartOfParameter*/ true);
|
||||
}
|
||||
function parseParameter() {
|
||||
var node = createNode(146 /* Parameter */);
|
||||
@@ -14252,7 +14253,7 @@ var ts;
|
||||
return parseTypeReference();
|
||||
}
|
||||
}
|
||||
function isStartOfType() {
|
||||
function isStartOfType(inStartOfParameter) {
|
||||
switch (token()) {
|
||||
case 119 /* AnyKeyword */:
|
||||
case 136 /* StringKeyword */:
|
||||
@@ -14279,11 +14280,11 @@ var ts;
|
||||
case 39 /* AsteriskToken */:
|
||||
return true;
|
||||
case 38 /* MinusToken */:
|
||||
return lookAhead(nextTokenIsNumericLiteral);
|
||||
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
|
||||
case 19 /* OpenParenToken */:
|
||||
// Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
|
||||
// or something that starts a type. We don't want to consider things like '(1)' a type.
|
||||
return lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
@@ -89385,7 +89386,9 @@ var ts;
|
||||
deleteCallback();
|
||||
}
|
||||
return {
|
||||
edits: changeTracker.getChanges()
|
||||
edits: changeTracker.getChanges(),
|
||||
renameFilename: undefined,
|
||||
renameLocation: undefined,
|
||||
};
|
||||
function deleteNode(node, inList) {
|
||||
if (inList === void 0) { inList = false; }
|
||||
@@ -89561,15 +89564,15 @@ var ts;
|
||||
var usedNames = ts.createMap();
|
||||
var i = 0;
|
||||
for (var _i = 0, extractions_1 = extractions; _i < extractions_1.length; _i++) {
|
||||
var extr = extractions_1[_i];
|
||||
var _a = extractions_1[_i], scopeDescription = _a.scopeDescription, errors = _a.errors;
|
||||
// Skip these since we don't have a way to report errors yet
|
||||
if (extr.errors && extr.errors.length) {
|
||||
if (errors.length) {
|
||||
continue;
|
||||
}
|
||||
// Don't issue refactorings with duplicated names.
|
||||
// Scopes come back in "innermost first" order, so extractions will
|
||||
// preferentially go into nearer scopes
|
||||
var description = ts.formatStringFromArgs(ts.Diagnostics.Extract_function_into_0.message, [extr.scopeDescription]);
|
||||
var description = ts.formatStringFromArgs(ts.Diagnostics.Extract_function_into_0.message, [scopeDescription]);
|
||||
if (!usedNames.has(description)) {
|
||||
usedNames.set(description, true);
|
||||
actions.push({
|
||||
@@ -89599,10 +89602,7 @@ var ts;
|
||||
ts.Debug.assert(!!parsedIndexMatch, "Scope name should have matched the regexp");
|
||||
var index = +parsedIndexMatch[1];
|
||||
ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the scope index");
|
||||
var extractions = getPossibleExtractions(targetRange, context, index);
|
||||
// Scope is no longer valid from when the user issued the refactor (??)
|
||||
ts.Debug.assert(extractions !== undefined, "The extraction went missing? How?");
|
||||
return ({ edits: extractions[0].changes });
|
||||
return getExtractionAtIndex(targetRange, context, index);
|
||||
}
|
||||
// Move these into diagnostic messages if they become user-facing
|
||||
var Messages;
|
||||
@@ -89635,13 +89635,14 @@ var ts;
|
||||
* The range is in a function which needs the 'static' modifier in a class
|
||||
*/
|
||||
RangeFacts[RangeFacts["InStaticRegion"] = 16] = "InStaticRegion";
|
||||
})(RangeFacts = extractMethod_1.RangeFacts || (extractMethod_1.RangeFacts = {}));
|
||||
})(RangeFacts || (RangeFacts = {}));
|
||||
/**
|
||||
* getRangeToExtract takes a span inside a text file and returns either an expression or an array
|
||||
* of statements representing the minimum set of nodes needed to extract the entire span. This
|
||||
* process may fail, in which case a set of errors is returned instead (these are currently
|
||||
* not shown to the user, but can be used by us diagnostically)
|
||||
*/
|
||||
// exported only for tests
|
||||
function getRangeToExtract(sourceFile, span) {
|
||||
var length = span.length || 0;
|
||||
// Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span.
|
||||
@@ -89927,7 +89928,7 @@ var ts;
|
||||
}
|
||||
function isValidExtractionTarget(node) {
|
||||
// Note that we don't use isFunctionLike because we don't want to put the extracted closure *inside* a method
|
||||
return (node.kind === 228 /* FunctionDeclaration */) || ts.isSourceFile(node) || isModuleBlock(node) || ts.isClassLike(node);
|
||||
return (node.kind === 228 /* FunctionDeclaration */) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node);
|
||||
}
|
||||
/**
|
||||
* Computes possible places we could extract the function into. For example,
|
||||
@@ -89965,14 +89966,29 @@ var ts;
|
||||
}
|
||||
return scopes;
|
||||
}
|
||||
extractMethod_1.collectEnclosingScopes = collectEnclosingScopes;
|
||||
// exported only for tests
|
||||
function getExtractionAtIndex(targetRange, context, requestedChangesIndex) {
|
||||
var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, errorsPerScope = _b.errorsPerScope;
|
||||
ts.Debug.assert(!errorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context);
|
||||
}
|
||||
extractMethod_1.getExtractionAtIndex = getExtractionAtIndex;
|
||||
/**
|
||||
* Given a piece of text to extract ('targetRange'), computes a list of possible extractions.
|
||||
* Each returned ExtractResultForScope corresponds to a possible target scope and is either a set of changes
|
||||
* or an error explaining why we can't extract into that scope.
|
||||
*/
|
||||
function getPossibleExtractions(targetRange, context, requestedChangesIndex) {
|
||||
if (requestedChangesIndex === void 0) { requestedChangesIndex = undefined; }
|
||||
// exported only for tests
|
||||
function getPossibleExtractions(targetRange, context) {
|
||||
var extractions = getPossibleExtractionsWorker(targetRange, context);
|
||||
// Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547
|
||||
return extractions && extractions.scopes.map(function (scope, i) {
|
||||
return ({ scopeDescription: getDescriptionForScope(scope), errors: extractions.readsAndWrites.errorsPerScope[i] });
|
||||
});
|
||||
}
|
||||
extractMethod_1.getPossibleExtractions = getPossibleExtractions;
|
||||
function getPossibleExtractionsWorker(targetRange, context) {
|
||||
var sourceFile = context.file;
|
||||
if (targetRange === undefined) {
|
||||
return undefined;
|
||||
@@ -89982,29 +89998,9 @@ var ts;
|
||||
return undefined;
|
||||
}
|
||||
var enclosingTextRange = getEnclosingTextRange(targetRange, sourceFile);
|
||||
var _a = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker()), target = _a.target, usagesPerScope = _a.usagesPerScope, errorsPerScope = _a.errorsPerScope;
|
||||
context.cancellationToken.throwIfCancellationRequested();
|
||||
if (requestedChangesIndex !== undefined) {
|
||||
if (errorsPerScope[requestedChangesIndex].length) {
|
||||
return undefined;
|
||||
}
|
||||
return [extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange, context)];
|
||||
}
|
||||
else {
|
||||
return scopes.map(function (scope, i) {
|
||||
var errors = errorsPerScope[i];
|
||||
if (errors.length) {
|
||||
return {
|
||||
scope: scope,
|
||||
scopeDescription: getDescriptionForScope(scope),
|
||||
errors: errors
|
||||
};
|
||||
}
|
||||
return { scope: scope, scopeDescription: getDescriptionForScope(scope) };
|
||||
});
|
||||
}
|
||||
var readsAndWrites = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker());
|
||||
return { scopes: scopes, readsAndWrites: readsAndWrites };
|
||||
}
|
||||
extractMethod_1.getPossibleExtractions = getPossibleExtractions;
|
||||
function getDescriptionForScope(scope) {
|
||||
if (ts.isFunctionLike(scope)) {
|
||||
switch (scope.kind) {
|
||||
@@ -90026,7 +90022,7 @@ var ts;
|
||||
return "'set " + scope.name.getText() + "'";
|
||||
}
|
||||
}
|
||||
else if (isModuleBlock(scope)) {
|
||||
else if (ts.isModuleBlock(scope)) {
|
||||
return "namespace '" + scope.parent.name.getText() + "'";
|
||||
}
|
||||
else if (ts.isClassLike(scope)) {
|
||||
@@ -90043,26 +90039,25 @@ var ts;
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
function getUniqueName(isNameOkay) {
|
||||
function getUniqueName(fileText) {
|
||||
var functionNameText = "newFunction";
|
||||
if (isNameOkay(functionNameText)) {
|
||||
return functionNameText;
|
||||
}
|
||||
var i = 1;
|
||||
while (!isNameOkay(functionNameText = "newFunction_" + i)) {
|
||||
i++;
|
||||
for (var i = 1; fileText.indexOf(functionNameText) !== -1; i++) {
|
||||
functionNameText = "newFunction_" + i;
|
||||
}
|
||||
return functionNameText;
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
function extractFunctionInScope(node, scope, _a, range, context) {
|
||||
var usagesInScope = _a.usages, substitutions = _a.substitutions;
|
||||
var checker = context.program.getTypeChecker();
|
||||
// Make a unique name for the extracted function
|
||||
var file = scope.getSourceFile();
|
||||
var functionNameText = getUniqueName(function (n) { return !file.identifiers.has(n); });
|
||||
var functionNameText = getUniqueName(file.text);
|
||||
var isJS = ts.isInJavaScriptFile(scope);
|
||||
var functionName = ts.createIdentifier(functionNameText);
|
||||
var functionReference = ts.createIdentifier(functionNameText);
|
||||
var returnType = undefined;
|
||||
var parameters = [];
|
||||
var callArguments = [];
|
||||
@@ -90093,7 +90088,7 @@ var ts;
|
||||
var contextualType = checker.getContextualType(node);
|
||||
returnType = checker.typeToTypeNode(contextualType);
|
||||
}
|
||||
var _b = transformFunctionBody(node), body = _b.body, returnValueProperty = _b.returnValueProperty;
|
||||
var _b = transformFunctionBody(node, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty;
|
||||
var newFunction;
|
||||
if (ts.isClassLike(scope)) {
|
||||
// always create private method in TypeScript files
|
||||
@@ -90119,7 +90114,8 @@ var ts;
|
||||
changeTracker.insertNodeBefore(context.file, scope.getLastToken(), newFunction, { prefix: context.newLineCharacter, suffix: context.newLineCharacter });
|
||||
var newNodes = [];
|
||||
// replace range with function call
|
||||
var call = ts.createCall(ts.isClassLike(scope) ? ts.createPropertyAccess(range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.getText()) : ts.createThis(), functionReference) : functionReference,
|
||||
var called = getCalledExpression(scope, range, functionNameText);
|
||||
var call = ts.createCall(called,
|
||||
/*typeArguments*/ undefined, callArguments);
|
||||
if (range.facts & RangeFacts.IsGenerator) {
|
||||
call = ts.createYield(ts.createToken(39 /* AsteriskToken */), call);
|
||||
@@ -90176,69 +90172,92 @@ var ts;
|
||||
else {
|
||||
changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes, { nodeSeparator: context.newLineCharacter });
|
||||
}
|
||||
return {
|
||||
scope: scope,
|
||||
scopeDescription: getDescriptionForScope(scope),
|
||||
changes: changeTracker.getChanges()
|
||||
};
|
||||
function getPropertyAssignmentsForWrites(writes) {
|
||||
return writes.map(function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
|
||||
}
|
||||
function generateReturnValueProperty() {
|
||||
return "__return";
|
||||
}
|
||||
function transformFunctionBody(body) {
|
||||
if (ts.isBlock(body) && !writes && substitutions.size === 0) {
|
||||
// already block, no writes to propagate back, no substitutions - can use node as is
|
||||
return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
var returnValueProperty;
|
||||
var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
|
||||
// rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
|
||||
if (writes || substitutions.size) {
|
||||
var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
|
||||
if (writes && !(range.facts & RangeFacts.HasReturn) && ts.isStatement(body)) {
|
||||
// add return at the end to propagate writes back in case if control flow falls out of the function body
|
||||
// it is ok to know that range has at least one return since it we only allow unconditional returns
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (assignments.length === 1) {
|
||||
rewrittenStatements.push(ts.createReturn(assignments[0].name));
|
||||
}
|
||||
else {
|
||||
rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
|
||||
}
|
||||
var edits = changeTracker.getChanges();
|
||||
var renameRange = isReadonlyArray(range.range) ? range.range[0] : range.range;
|
||||
var renameFilename = renameRange.getSourceFile().fileName;
|
||||
var renameLocation = getRenameLocation(edits, renameFilename, functionNameText);
|
||||
return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits };
|
||||
}
|
||||
function getRenameLocation(edits, renameFilename, functionNameText) {
|
||||
var delta = 0;
|
||||
for (var _i = 0, edits_1 = edits; _i < edits_1.length; _i++) {
|
||||
var _a = edits_1[_i], fileName = _a.fileName, textChanges_1 = _a.textChanges;
|
||||
ts.Debug.assert(fileName === renameFilename);
|
||||
for (var _b = 0, textChanges_2 = textChanges_1; _b < textChanges_2.length; _b++) {
|
||||
var change = textChanges_2[_b];
|
||||
var span_17 = change.span, newText = change.newText;
|
||||
// TODO(acasey): We are assuming that the call expression comes before the function declaration,
|
||||
// because we want the new cursor to be on the call expression,
|
||||
// which is closer to where the user was before extracting the function.
|
||||
var index = newText.indexOf(functionNameText);
|
||||
if (index !== -1) {
|
||||
return span_17.start + delta + index;
|
||||
}
|
||||
return { body: ts.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty: returnValueProperty };
|
||||
delta += newText.length - span_17.length;
|
||||
}
|
||||
else {
|
||||
return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
function visitor(node) {
|
||||
if (node.kind === 219 /* ReturnStatement */ && writes) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (node.expression) {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = generateReturnValueProperty();
|
||||
}
|
||||
assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return ts.createReturn(assignments[0].name);
|
||||
}
|
||||
else {
|
||||
return ts.createReturn(ts.createObjectLiteral(assignments));
|
||||
}
|
||||
}
|
||||
throw new Error(); // Didn't find the text we inserted?
|
||||
}
|
||||
function getCalledExpression(scope, range, functionNameText) {
|
||||
var functionReference = ts.createIdentifier(functionNameText);
|
||||
if (ts.isClassLike(scope)) {
|
||||
var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis();
|
||||
return ts.createPropertyAccess(lhs, functionReference);
|
||||
}
|
||||
else {
|
||||
return functionReference;
|
||||
}
|
||||
}
|
||||
function transformFunctionBody(body, writes, substitutions, hasReturn) {
|
||||
if (ts.isBlock(body) && !writes && substitutions.size === 0) {
|
||||
// already block, no writes to propagate back, no substitutions - can use node as is
|
||||
return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
var returnValueProperty;
|
||||
var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
|
||||
// rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
|
||||
if (writes || substitutions.size) {
|
||||
var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
|
||||
if (writes && !hasReturn && ts.isStatement(body)) {
|
||||
// add return at the end to propagate writes back in case if control flow falls out of the function body
|
||||
// it is ok to know that range has at least one return since it we only allow unconditional returns
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (assignments.length === 1) {
|
||||
rewrittenStatements.push(ts.createReturn(assignments[0].name));
|
||||
}
|
||||
else {
|
||||
var substitution = substitutions.get(ts.getNodeId(node).toString());
|
||||
return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext);
|
||||
rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
|
||||
}
|
||||
}
|
||||
return { body: ts.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty: returnValueProperty };
|
||||
}
|
||||
else {
|
||||
return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined };
|
||||
}
|
||||
function visitor(node) {
|
||||
if (node.kind === 219 /* ReturnStatement */ && writes) {
|
||||
var assignments = getPropertyAssignmentsForWrites(writes);
|
||||
if (node.expression) {
|
||||
if (!returnValueProperty) {
|
||||
returnValueProperty = "__return";
|
||||
}
|
||||
assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
|
||||
}
|
||||
if (assignments.length === 1) {
|
||||
return ts.createReturn(assignments[0].name);
|
||||
}
|
||||
else {
|
||||
return ts.createReturn(ts.createObjectLiteral(assignments));
|
||||
}
|
||||
}
|
||||
else {
|
||||
var substitution = substitutions.get(ts.getNodeId(node).toString());
|
||||
return substitution || ts.visitEachChild(node, visitor, ts.nullTransformationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
extractMethod_1.extractFunctionInScope = extractFunctionInScope;
|
||||
function isModuleBlock(n) {
|
||||
return n.kind === 234 /* ModuleBlock */;
|
||||
function getPropertyAssignmentsForWrites(writes) {
|
||||
return writes.map(function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
|
||||
}
|
||||
function isReadonlyArray(v) {
|
||||
return ts.isArray(v);
|
||||
|
||||
@@ -11098,7 +11098,8 @@ var ts;
|
||||
return token() === 24 ||
|
||||
isIdentifierOrPattern() ||
|
||||
ts.isModifierKind(token()) ||
|
||||
token() === 57 || isStartOfType();
|
||||
token() === 57 ||
|
||||
isStartOfType(true);
|
||||
}
|
||||
function parseParameter() {
|
||||
var node = createNode(146);
|
||||
@@ -11437,7 +11438,7 @@ var ts;
|
||||
return parseTypeReference();
|
||||
}
|
||||
}
|
||||
function isStartOfType() {
|
||||
function isStartOfType(inStartOfParameter) {
|
||||
switch (token()) {
|
||||
case 119:
|
||||
case 136:
|
||||
@@ -11464,9 +11465,9 @@ var ts;
|
||||
case 39:
|
||||
return true;
|
||||
case 38:
|
||||
return lookAhead(nextTokenIsNumericLiteral);
|
||||
return !inStartOfParameter && lookAhead(nextTokenIsNumericLiteral);
|
||||
case 19:
|
||||
return lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user