/*1*/ >` (with a closing `>`), the completion list will contain "div".
- var tagName = location.parent.parent.openingElement.tagName;
- var hasClosingAngleBracket = !!ts.findChildOfKind(location.parent, 31 /* GreaterThanToken */, sourceFile);
- var entry = {
- name: tagName.getFullText(sourceFile) + (hasClosingAngleBracket ? "" : ">"),
- kind: "class" /* classElement */,
- kindModifiers: undefined,
- sortText: SortText.LocationPriority,
- };
- return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, entries: [entry] };
- }
- var entries = [];
- if (isUncheckedFile(sourceFile, compilerOptions)) {
- var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries,
- /* contextToken */ undefined, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, completionData.isJsxIdentifierExpected, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap, symbolToSortTextMap);
- getJSCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries); // TODO: GH#18217
- }
- else {
- if (!isNewIdentifierLocation && (!symbols || symbols.length === 0) && keywordFilters === 0 /* None */) {
- return undefined;
- }
- getCompletionEntriesFromSymbols(symbols, entries,
- /* contextToken */ undefined, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, preferences, propertyAccessToConvert, completionData.isJsxIdentifierExpected, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap, symbolToSortTextMap);
- }
- if (keywordFilters !== 0 /* None */) {
- var entryNames = ts.arrayToSet(entries, function (e) { return e.name; });
- for (var _i = 0, _a = getKeywordCompletions(keywordFilters, !insideJsDocTagTypeExpression && ts.isSourceFileJS(sourceFile)); _i < _a.length; _i++) {
- var keywordEntry = _a[_i];
- if (!entryNames.has(keywordEntry.name)) {
- entries.push(keywordEntry);
- }
- }
- }
- for (var _b = 0, literals_1 = literals; _b < literals_1.length; _b++) {
- var literal = literals_1[_b];
- entries.push(createCompletionEntryForLiteral(literal, preferences));
- }
- return { isGlobalCompletion: isInSnippetScope, isMemberCompletion: isMemberCompletionKind(completionKind), isNewIdentifierLocation: isNewIdentifierLocation, entries: entries };
- }
- function isUncheckedFile(sourceFile, compilerOptions) {
- return ts.isSourceFileJS(sourceFile) && !ts.isCheckJsEnabledForFile(sourceFile, compilerOptions);
- }
- function isMemberCompletionKind(kind) {
- switch (kind) {
- case 0 /* ObjectPropertyDeclaration */:
- case 3 /* MemberLike */:
- case 2 /* PropertyAccess */:
- return true;
- default:
- return false;
- }
- }
- function getJSCompletionEntries(sourceFile, position, uniqueNames, target, entries) {
- ts.getNameTable(sourceFile).forEach(function (pos, name) {
- // Skip identifiers produced only from the current location
- if (pos === position) {
- return;
- }
- var realName = ts.unescapeLeadingUnderscores(name);
- if (!uniqueNames.has(realName) && ts.isIdentifierText(realName, target)) {
- uniqueNames.add(realName);
- entries.push({
- name: realName,
- kind: "warning" /* warning */,
- kindModifiers: "",
- sortText: SortText.JavascriptIdentifiers,
- isFromUncheckedFile: true
- });
- }
- });
- }
- function completionNameForLiteral(literal, preferences) {
- return typeof literal === "object" ? ts.pseudoBigIntToString(literal) + "n" :
- ts.isString(literal) ? ts.quote(literal, preferences) : JSON.stringify(literal);
- }
- function createCompletionEntryForLiteral(literal, preferences) {
- return { name: completionNameForLiteral(literal, preferences), kind: "string" /* string */, kindModifiers: "" /* none */, sortText: SortText.LocationPriority };
- }
- function createCompletionEntry(symbol, sortText, contextToken, location, sourceFile, typeChecker, name, needsConvertPropertyAccess, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, preferences) {
- var insertText;
- var replacementSpan = ts.getReplacementSpanForContextToken(contextToken);
- var insertQuestionDot = origin && originIsNullableMember(origin);
- var useBraces = origin && originIsSymbolMember(origin) || needsConvertPropertyAccess;
- if (origin && originIsThisType(origin)) {
- insertText = needsConvertPropertyAccess
- ? "this" + (insertQuestionDot ? "?." : "") + "[" + quotePropertyName(name, preferences) + "]"
- : "this" + (insertQuestionDot ? "?." : ".") + name;
- }
- // We should only have needsConvertPropertyAccess if there's a property access to convert. But see #21790.
- // Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro.
- else if ((useBraces || insertQuestionDot) && propertyAccessToConvert) {
- insertText = useBraces ? needsConvertPropertyAccess ? "[" + quotePropertyName(name, preferences) + "]" : "[" + name + "]" : name;
- if (insertQuestionDot || propertyAccessToConvert.questionDotToken) {
- insertText = "?." + insertText;
- }
- var dot = ts.findChildOfKind(propertyAccessToConvert, 24 /* DotToken */, sourceFile) ||
- ts.findChildOfKind(propertyAccessToConvert, 28 /* QuestionDotToken */, sourceFile);
- if (!dot) {
- return undefined;
- }
- // If the text after the '.' starts with this name, write over it. Else, add new text.
- var end = ts.startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end;
- replacementSpan = ts.createTextSpanFromBounds(dot.getStart(sourceFile), end);
- }
- if (isJsxInitializer) {
- if (insertText === undefined)
- insertText = name;
- insertText = "{" + insertText + "}";
- if (typeof isJsxInitializer !== "boolean") {
- replacementSpan = ts.createTextSpanFromNode(isJsxInitializer, sourceFile);
- }
- }
- if (origin && originIsPromise(origin) && propertyAccessToConvert) {
- if (insertText === undefined)
- insertText = name;
- var precedingToken = ts.findPrecedingToken(propertyAccessToConvert.pos, sourceFile);
- var awaitText = "";
- if (precedingToken && ts.positionIsASICandidate(precedingToken.end, precedingToken.parent, sourceFile)) {
- awaitText = ";";
- }
- awaitText += "(await " + propertyAccessToConvert.expression.getText() + ")";
- insertText = needsConvertPropertyAccess ? "" + awaitText + insertText : "" + awaitText + (insertQuestionDot ? "?." : ".") + insertText;
- replacementSpan = ts.createTextSpanFromBounds(propertyAccessToConvert.getStart(sourceFile), propertyAccessToConvert.end);
- }
- if (insertText !== undefined && !preferences.includeCompletionsWithInsertText) {
- return undefined;
- }
- // TODO(drosen): Right now we just permit *all* semantic meanings when calling
- // 'getSymbolKind' which is permissible given that it is backwards compatible; but
- // really we should consider passing the meaning for the node so that we don't report
- // that a suggestion for a value is an interface. We COULD also just do what
- // 'getSymbolModifiers' does, which is to use the first declaration.
- // Use a 'sortText' of 0' so that all symbol completion entries come before any other
- // entries (like JavaScript identifier entries).
- return {
- name: name,
- kind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, location),
- kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol),
- sortText: sortText,
- source: getSourceFromOrigin(origin),
- hasAction: origin && originIsExport(origin) || undefined,
- isRecommended: isRecommendedCompletionMatch(symbol, recommendedCompletion, typeChecker) || undefined,
- insertText: insertText,
- replacementSpan: replacementSpan,
- };
- }
- function quotePropertyName(name, preferences) {
- if (/^\d+$/.test(name)) {
- return name;
- }
- return ts.quote(name, preferences);
- }
- function isRecommendedCompletionMatch(localSymbol, recommendedCompletion, checker) {
- return localSymbol === recommendedCompletion ||
- !!(localSymbol.flags & 1048576 /* ExportValue */) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion;
- }
- function getSourceFromOrigin(origin) {
- if (originIsExport(origin)) {
- return ts.stripQuotes(origin.moduleSymbol.name);
- }
- if ((origin === null || origin === void 0 ? void 0 : origin.kind) === 1 /* ThisType */) {
- return CompletionSource.ThisProperty;
- }
- }
- function getCompletionEntriesFromSymbols(symbols, entries, contextToken, location, sourceFile, typeChecker, target, log, kind, preferences, propertyAccessToConvert, jsxIdentifierExpected, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap, symbolToSortTextMap) {
- var start = ts.timestamp();
- // Tracks unique names.
- // Value is set to false for global variables or completions from external module exports, because we can have multiple of those;
- // true otherwise. Based on the order we add things we will always see locals first, then globals, then module exports.
- // So adding a completion for a local will prevent us from adding completions for external module exports sharing the same name.
- var uniques = ts.createMap();
- for (var _i = 0, symbols_1 = symbols; _i < symbols_1.length; _i++) {
- var symbol = symbols_1[_i];
- var origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[ts.getSymbolId(symbol)] : undefined;
- var info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind, !!jsxIdentifierExpected);
- if (!info) {
- continue;
- }
- var name = info.name, needsConvertPropertyAccess = info.needsConvertPropertyAccess;
- if (uniques.get(name)) {
- continue;
- }
- var entry = createCompletionEntry(symbol, symbolToSortTextMap && symbolToSortTextMap[ts.getSymbolId(symbol)] || SortText.LocationPriority, contextToken, location, sourceFile, typeChecker, name, needsConvertPropertyAccess, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, preferences);
- if (!entry) {
- continue;
- }
- /** True for locals; false for globals, module exports from other files, `this.` completions. */
- var shouldShadowLaterSymbols = !origin && !(symbol.parent === undefined && !ts.some(symbol.declarations, function (d) { return d.getSourceFile() === location.getSourceFile(); }));
- uniques.set(name, shouldShadowLaterSymbols);
- entries.push(entry);
- }
- log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (ts.timestamp() - start));
- // Prevent consumers of this map from having to worry about
- // the boolean value. Externally, it should be seen as the
- // set of all names.
- return {
- has: function (name) { return uniques.has(name); },
- add: function (name) { return uniques.set(name, true); },
- };
- }
- Completions.getCompletionEntriesFromSymbols = getCompletionEntriesFromSymbols;
- function getLabelCompletionAtPosition(node) {
- var entries = getLabelStatementCompletions(node);
- if (entries.length) {
- return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries };
- }
- }
- function getLabelStatementCompletions(node) {
- var entries = [];
- var uniques = ts.createMap();
- var current = node;
- while (current) {
- if (ts.isFunctionLike(current)) {
- break;
- }
- if (ts.isLabeledStatement(current)) {
- var name = current.label.text;
- if (!uniques.has(name)) {
- uniques.set(name, true);
- entries.push({
- name: name,
- kindModifiers: "" /* none */,
- kind: "label" /* label */,
- sortText: SortText.LocationPriority
- });
- }
- }
- current = current.parent;
- }
- return entries;
- }
- function getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId, host, preferences) {
- var compilerOptions = program.getCompilerOptions();
- var completionData = getCompletionData(program, log, sourceFile, isUncheckedFile(sourceFile, compilerOptions), position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, entryId, host);
- if (!completionData) {
- return { type: "none" };
- }
- if (completionData.kind !== 0 /* Data */) {
- return { type: "request", request: completionData };
- }
- var symbols = completionData.symbols, literals = completionData.literals, location = completionData.location, completionKind = completionData.completionKind, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, previousToken = completionData.previousToken, isJsxInitializer = completionData.isJsxInitializer, isTypeOnlyLocation = completionData.isTypeOnlyLocation;
- var literal = ts.find(literals, function (l) { return completionNameForLiteral(l, preferences) === entryId.name; });
- if (literal !== undefined)
- return { type: "literal", literal: literal };
- // Find the symbol with the matching entry name.
- // We don't need to perform character checks here because we're only comparing the
- // name against 'entryName' (which is known to be good), not building a new
- // completion entry.
- return ts.firstDefined(symbols, function (symbol) {
- var origin = symbolToOriginInfoMap[ts.getSymbolId(symbol)];
- var info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind, completionData.isJsxIdentifierExpected);
- return info && info.name === entryId.name && getSourceFromOrigin(origin) === entryId.source
- ? { type: "symbol", symbol: symbol, location: location, symbolToOriginInfoMap: symbolToOriginInfoMap, previousToken: previousToken, isJsxInitializer: isJsxInitializer, isTypeOnlyLocation: isTypeOnlyLocation }
- : undefined;
- }) || { type: "none" };
- }
- function getCompletionEntryDetails(program, log, sourceFile, position, entryId, host, formatContext, preferences, cancellationToken) {
- var typeChecker = program.getTypeChecker();
- var compilerOptions = program.getCompilerOptions();
- var name = entryId.name;
- var contextToken = ts.findPrecedingToken(position, sourceFile);
- if (ts.isInString(sourceFile, position, contextToken)) {
- return Completions.StringCompletions.getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, typeChecker, compilerOptions, host, cancellationToken);
- }
- // Compute all the completion symbols again.
- var symbolCompletion = getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId, host, preferences);
- switch (symbolCompletion.type) {
- case "request": {
- var request = symbolCompletion.request;
- switch (request.kind) {
- case 1 /* JsDocTagName */:
- return ts.JsDoc.getJSDocTagNameCompletionDetails(name);
- case 2 /* JsDocTag */:
- return ts.JsDoc.getJSDocTagCompletionDetails(name);
- case 3 /* JsDocParameterName */:
- return ts.JsDoc.getJSDocParameterNameCompletionDetails(name);
- default:
- return ts.Debug.assertNever(request);
- }
- }
- case "symbol": {
- var symbol = symbolCompletion.symbol, location = symbolCompletion.location, symbolToOriginInfoMap = symbolCompletion.symbolToOriginInfoMap, previousToken = symbolCompletion.previousToken;
- var _a = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, position, previousToken, formatContext, preferences), codeActions = _a.codeActions, sourceDisplay = _a.sourceDisplay;
- return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay); // TODO: GH#18217
- }
- case "literal": {
- var literal = symbolCompletion.literal;
- return createSimpleDetails(completionNameForLiteral(literal, preferences), "string" /* string */, typeof literal === "string" ? ts.SymbolDisplayPartKind.stringLiteral : ts.SymbolDisplayPartKind.numericLiteral);
- }
- case "none":
- // Didn't find a symbol with this name. See if we can find a keyword instead.
- return allKeywordsCompletions().some(function (c) { return c.name === name; }) ? createSimpleDetails(name, "keyword" /* keyword */, ts.SymbolDisplayPartKind.keyword) : undefined;
- default:
- ts.Debug.assertNever(symbolCompletion);
- }
- }
- Completions.getCompletionEntryDetails = getCompletionEntryDetails;
- function createSimpleDetails(name, kind, kind2) {
- return createCompletionDetails(name, "" /* none */, kind, [ts.displayPart(name, kind2)]);
- }
- function createCompletionDetailsForSymbol(symbol, checker, sourceFile, location, cancellationToken, codeActions, sourceDisplay) {
- var _a = checker.runWithCancellationToken(cancellationToken, function (checker) {
- return ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, 7 /* All */);
- }), displayParts = _a.displayParts, documentation = _a.documentation, symbolKind = _a.symbolKind, tags = _a.tags;
- return createCompletionDetails(symbol.name, ts.SymbolDisplay.getSymbolModifiers(symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay);
- }
- Completions.createCompletionDetailsForSymbol = createCompletionDetailsForSymbol;
- function createCompletionDetails(name, kindModifiers, kind, displayParts, documentation, tags, codeActions, source) {
- return { name: name, kindModifiers: kindModifiers, kind: kind, displayParts: displayParts, documentation: documentation, tags: tags, codeActions: codeActions, source: source };
- }
- Completions.createCompletionDetails = createCompletionDetails;
- function getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, checker, host, compilerOptions, sourceFile, position, previousToken, formatContext, preferences) {
- var symbolOriginInfo = symbolToOriginInfoMap[ts.getSymbolId(symbol)];
- if (!symbolOriginInfo || !originIsExport(symbolOriginInfo)) {
- return { codeActions: undefined, sourceDisplay: undefined };
- }
- var moduleSymbol = symbolOriginInfo.moduleSymbol;
- var exportedSymbol = checker.getMergedSymbol(ts.skipAlias(symbol.exportSymbol || symbol, checker));
- var _a = ts.codefix.getImportCompletionAction(exportedSymbol, moduleSymbol, sourceFile, ts.getNameForExportedSymbol(symbol, compilerOptions.target), host, program, formatContext, previousToken && ts.isIdentifier(previousToken) ? previousToken.getStart(sourceFile) : position, preferences), moduleSpecifier = _a.moduleSpecifier, codeAction = _a.codeAction;
- return { sourceDisplay: [ts.textPart(moduleSpecifier)], codeActions: [codeAction] };
- }
- function getCompletionEntrySymbol(program, log, sourceFile, position, entryId, host, preferences) {
- var completion = getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId, host, preferences);
- return completion.type === "symbol" ? completion.symbol : undefined;
- }
- Completions.getCompletionEntrySymbol = getCompletionEntrySymbol;
- var CompletionDataKind;
- (function (CompletionDataKind) {
- CompletionDataKind[CompletionDataKind["Data"] = 0] = "Data";
- CompletionDataKind[CompletionDataKind["JsDocTagName"] = 1] = "JsDocTagName";
- CompletionDataKind[CompletionDataKind["JsDocTag"] = 2] = "JsDocTag";
- CompletionDataKind[CompletionDataKind["JsDocParameterName"] = 3] = "JsDocParameterName";
- })(CompletionDataKind || (CompletionDataKind = {}));
- var CompletionKind;
- (function (CompletionKind) {
- CompletionKind[CompletionKind["ObjectPropertyDeclaration"] = 0] = "ObjectPropertyDeclaration";
- CompletionKind[CompletionKind["Global"] = 1] = "Global";
- CompletionKind[CompletionKind["PropertyAccess"] = 2] = "PropertyAccess";
- CompletionKind[CompletionKind["MemberLike"] = 3] = "MemberLike";
- CompletionKind[CompletionKind["String"] = 4] = "String";
- CompletionKind[CompletionKind["None"] = 5] = "None";
- })(CompletionKind = Completions.CompletionKind || (Completions.CompletionKind = {}));
- function getRecommendedCompletion(previousToken, contextualType, checker) {
- // For a union, return the first one with a recommended completion.
- return ts.firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), function (type) {
- var symbol = type && type.symbol;
- // Don't include make a recommended completion for an abstract class
- return symbol && (symbol.flags & (8 /* EnumMember */ | 384 /* Enum */ | 32 /* Class */) && !ts.isAbstractConstructorSymbol(symbol))
- ? getFirstSymbolInChain(symbol, previousToken, checker)
- : undefined;
- });
- }
- function getContextualType(previousToken, position, sourceFile, checker) {
- var parent = previousToken.parent;
- switch (previousToken.kind) {
- case 75 /* Identifier */:
- return ts.getContextualTypeFromParent(previousToken, checker);
- case 62 /* EqualsToken */:
- switch (parent.kind) {
- case 242 /* VariableDeclaration */:
- return checker.getContextualType(parent.initializer); // TODO: GH#18217
- case 209 /* BinaryExpression */:
- return checker.getTypeAtLocation(parent.left);
- case 273 /* JsxAttribute */:
- return checker.getContextualTypeForJsxAttribute(parent);
- default:
- return undefined;
- }
- case 99 /* NewKeyword */:
- return checker.getContextualType(parent);
- case 78 /* CaseKeyword */:
- return ts.getSwitchedType(ts.cast(parent, ts.isCaseClause), checker);
- case 18 /* OpenBraceToken */:
- return ts.isJsxExpression(parent) && parent.parent.kind !== 266 /* JsxElement */ ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined;
- default:
- var argInfo = ts.SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile);
- return argInfo ?
- // At `,`, treat this as the next argument after the comma.
- checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === 27 /* CommaToken */ ? 1 : 0)) :
- ts.isEqualityOperatorKind(previousToken.kind) && ts.isBinaryExpression(parent) && ts.isEqualityOperatorKind(parent.operatorToken.kind) ?
- // completion at `x ===/**/` should be for the right side
- checker.getTypeAtLocation(parent.left) :
- checker.getContextualType(previousToken);
- }
- }
- function getFirstSymbolInChain(symbol, enclosingDeclaration, checker) {
- var chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ 67108863 /* All */, /*useOnlyExternalAliasing*/ false);
- if (chain)
- return ts.first(chain);
- return symbol.parent && (isModuleSymbol(symbol.parent) ? symbol : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker));
- }
- function isModuleSymbol(symbol) {
- return symbol.declarations.some(function (d) { return d.kind === 290 /* SourceFile */; });
- }
- function getCompletionData(program, log, sourceFile, isUncheckedFile, position, preferences, detailsEntryId, host) {
- var typeChecker = program.getTypeChecker();
- var start = ts.timestamp();
- var currentToken = ts.getTokenAtPosition(sourceFile, position); // TODO: GH#15853
- // We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.)
- log("getCompletionData: Get current token: " + (ts.timestamp() - start));
- start = ts.timestamp();
- var insideComment = ts.isInComment(sourceFile, position, currentToken);
- log("getCompletionData: Is inside comment: " + (ts.timestamp() - start));
- var insideJsDocTagTypeExpression = false;
- var isInSnippetScope = false;
- if (insideComment) {
- if (ts.hasDocComment(sourceFile, position)) {
- if (sourceFile.text.charCodeAt(position - 1) === 64 /* at */) {
- // The current position is next to the '@' sign, when no tag name being provided yet.
- // Provide a full list of tag names
- return { kind: 1 /* JsDocTagName */ };
- }
- else {
- // When completion is requested without "@", we will have check to make sure that
- // there are no comments prefix the request position. We will only allow "*" and space.
- // e.g
- // /** |c| /*
- //
- // /**
- // |c|
- // */
- //
- // /**
- // * |c|
- // */
- //
- // /**
- // * |c|
- // */
- var lineStart = ts.getLineStartPositionForPosition(position, sourceFile);
- if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) {
- return { kind: 2 /* JsDocTag */ };
- }
- }
- }
- // Completion should work inside certain JsDoc tags. For example:
- // /** @type {number | string} */
- // Completion should work in the brackets
- var tag = getJsDocTagAtPosition(currentToken, position);
- if (tag) {
- if (tag.tagName.pos <= position && position <= tag.tagName.end) {
- return { kind: 1 /* JsDocTagName */ };
- }
- if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === 294 /* JSDocTypeExpression */) {
- currentToken = ts.getTokenAtPosition(sourceFile, position);
- if (!currentToken ||
- (!ts.isDeclarationName(currentToken) &&
- (currentToken.parent.kind !== 323 /* JSDocPropertyTag */ ||
- currentToken.parent.name !== currentToken))) {
- // Use as type location if inside tag's type expression
- insideJsDocTagTypeExpression = isCurrentlyEditingNode(tag.typeExpression);
- }
- }
- if (!insideJsDocTagTypeExpression && ts.isJSDocParameterTag(tag) && (ts.nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) {
- return { kind: 3 /* JsDocParameterName */, tag: tag };
- }
- }
- if (!insideJsDocTagTypeExpression) {
- // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal
- // comment or the plain text part of a jsDoc comment, so no completion should be available
- log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment.");
- return undefined;
- }
- }
- start = ts.timestamp();
- var previousToken = ts.findPrecedingToken(position, sourceFile, /*startNode*/ undefined); // TODO: GH#18217
- log("getCompletionData: Get previous token 1: " + (ts.timestamp() - start));
- // The decision to provide completion depends on the contextToken, which is determined through the previousToken.
- // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file
- var contextToken = previousToken;
- // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
- // Skip this partial identifier and adjust the contextToken to the token that precedes it.
- if (contextToken && position <= contextToken.end && (ts.isIdentifierOrPrivateIdentifier(contextToken) || ts.isKeyword(contextToken.kind))) {
- var start_1 = ts.timestamp();
- contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined); // TODO: GH#18217
- log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_1));
- }
- // Find the node where completion is requested on.
- // Also determine whether we are trying to complete with members of that node
- // or attributes of a JSX tag.
- var node = currentToken;
- var propertyAccessToConvert;
- var isRightOfDot = false;
- var isRightOfQuestionDot = false;
- var isRightOfOpenTag = false;
- var isStartingCloseTag = false;
- var isJsxInitializer = false;
- var isJsxIdentifierExpected = false;
- var location = ts.getTouchingPropertyName(sourceFile, position);
- if (contextToken) {
- // Bail out if this is a known invalid completion location
- if (isCompletionListBlocker(contextToken)) {
- log("Returning an empty list because completion was requested in an invalid position.");
- return undefined;
- }
- var parent = contextToken.parent;
- if (contextToken.kind === 24 /* DotToken */ || contextToken.kind === 28 /* QuestionDotToken */) {
- isRightOfDot = contextToken.kind === 24 /* DotToken */;
- isRightOfQuestionDot = contextToken.kind === 28 /* QuestionDotToken */;
- switch (parent.kind) {
- case 194 /* PropertyAccessExpression */:
- propertyAccessToConvert = parent;
- node = propertyAccessToConvert.expression;
- if (node.end === contextToken.pos &&
- ts.isCallExpression(node) &&
- node.getChildCount(sourceFile) &&
- ts.last(node.getChildren(sourceFile)).kind !== 21 /* CloseParenToken */) {
- // This is likely dot from incorrectly parsed call expression and user is starting to write spread
- // eg: Math.min(./**/)
- return undefined;
- }
- break;
- case 153 /* QualifiedName */:
- node = parent.left;
- break;
- case 249 /* ModuleDeclaration */:
- node = parent.name;
- break;
- case 188 /* ImportType */:
- case 219 /* MetaProperty */:
- node = parent;
- break;
- default:
- // There is nothing that precedes the dot, so this likely just a stray character
- // or leading into a '...' token. Just bail out instead.
- return undefined;
- }
- }
- else if (sourceFile.languageVariant === 1 /* JSX */) {
- //
- // If the tagname is a property access expression, we will then walk up to the top most of property access expression.
- // Then, try to get a JSX container and its associated attributes type.
- if (parent && parent.kind === 194 /* PropertyAccessExpression */) {
- contextToken = parent;
- parent = parent.parent;
- }
- // Fix location
- if (currentToken.parent === location) {
- switch (currentToken.kind) {
- case 31 /* GreaterThanToken */:
- if (currentToken.parent.kind === 266 /* JsxElement */ || currentToken.parent.kind === 268 /* JsxOpeningElement */) {
- location = currentToken;
- }
- break;
- case 43 /* SlashToken */:
- if (currentToken.parent.kind === 267 /* JsxSelfClosingElement */) {
- location = currentToken;
- }
- break;
- }
- }
- switch (parent.kind) {
- case 269 /* JsxClosingElement */:
- if (contextToken.kind === 43 /* SlashToken */) {
- isStartingCloseTag = true;
- location = contextToken;
- }
- break;
- case 209 /* BinaryExpression */:
- if (!binaryExpressionMayBeOpenTag(parent)) {
- break;
- }
- // falls through
- case 267 /* JsxSelfClosingElement */:
- case 266 /* JsxElement */:
- case 268 /* JsxOpeningElement */:
- isJsxIdentifierExpected = true;
- if (contextToken.kind === 29 /* LessThanToken */) {
- isRightOfOpenTag = true;
- location = contextToken;
- }
- break;
- case 273 /* JsxAttribute */:
- switch (previousToken.kind) {
- case 62 /* EqualsToken */:
- isJsxInitializer = true;
- break;
- case 75 /* Identifier */:
- isJsxIdentifierExpected = true;
- // For `
` we don't want to treat this as a jsx inializer, instead it's the attribute name.
- if (parent !== previousToken.parent &&
- !parent.initializer &&
- ts.findChildOfKind(parent, 62 /* EqualsToken */, sourceFile)) {
- isJsxInitializer = previousToken;
- }
- }
- break;
- }
- }
- }
- var semanticStart = ts.timestamp();
- var completionKind = 5 /* None */;
- var isNewIdentifierLocation = false;
- var keywordFilters = 0 /* None */;
- // This also gets mutated in nested-functions after the return
- var symbols = [];
- var symbolToOriginInfoMap = [];
- var symbolToSortTextMap = [];
- var importSuggestionsCache = host.getImportSuggestionsCache && host.getImportSuggestionsCache();
- var isTypeOnly = isTypeOnlyCompletion();
- if (isRightOfDot || isRightOfQuestionDot) {
- getTypeScriptMemberSymbols();
- }
- else if (isRightOfOpenTag) {
- var tagSymbols = typeChecker.getJsxIntrinsicTagNamesAt(location);
- ts.Debug.assertEachIsDefined(tagSymbols, "getJsxIntrinsicTagNames() should all be defined");
- tryGetGlobalSymbols();
- symbols = tagSymbols.concat(symbols);
- completionKind = 3 /* MemberLike */;
- keywordFilters = 0 /* None */;
- }
- else if (isStartingCloseTag) {
- var tagName = contextToken.parent.parent.openingElement.tagName;
- var tagSymbol = typeChecker.getSymbolAtLocation(tagName);
- if (tagSymbol) {
- symbols = [tagSymbol];
- }
- completionKind = 3 /* MemberLike */;
- keywordFilters = 0 /* None */;
- }
- else {
- // For JavaScript or TypeScript, if we're not after a dot, then just try to get the
- // global symbols in scope. These results should be valid for either language as
- // the set of symbols that can be referenced from this location.
- if (!tryGetGlobalSymbols()) {
- return undefined;
- }
- }
- log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart));
- var contextualType = previousToken && getContextualType(previousToken, position, sourceFile, typeChecker);
- var literals = ts.mapDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), function (t) { return t.isLiteral() ? t.value : undefined; });
- var recommendedCompletion = previousToken && contextualType && getRecommendedCompletion(previousToken, contextualType, typeChecker);
- return {
- kind: 0 /* Data */,
- symbols: symbols,
- completionKind: completionKind,
- isInSnippetScope: isInSnippetScope,
- propertyAccessToConvert: propertyAccessToConvert,
- isNewIdentifierLocation: isNewIdentifierLocation,
- location: location,
- keywordFilters: keywordFilters,
- literals: literals,
- symbolToOriginInfoMap: symbolToOriginInfoMap,
- recommendedCompletion: recommendedCompletion,
- previousToken: previousToken,
- isJsxInitializer: isJsxInitializer,
- insideJsDocTagTypeExpression: insideJsDocTagTypeExpression,
- symbolToSortTextMap: symbolToSortTextMap,
- isTypeOnlyLocation: isTypeOnly,
- isJsxIdentifierExpected: isJsxIdentifierExpected,
- };
- function isTagWithTypeExpression(tag) {
- switch (tag.kind) {
- case 317 /* JSDocParameterTag */:
- case 323 /* JSDocPropertyTag */:
- case 318 /* JSDocReturnTag */:
- case 320 /* JSDocTypeTag */:
- case 322 /* JSDocTypedefTag */:
- return true;
- default:
- return false;
- }
- }
- function getTypeScriptMemberSymbols() {
- // Right of dot member completion list
- completionKind = 2 /* PropertyAccess */;
- // Since this is qualified name check it's a type node location
- var isImportType = ts.isLiteralImportTypeNode(node);
- var isTypeLocation = insideJsDocTagTypeExpression
- || (isImportType && !node.isTypeOf)
- || ts.isPartOfTypeNode(node.parent)
- || ts.isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker);
- var isRhsOfImportDeclaration = ts.isInRightSideOfInternalImportEqualsDeclaration(node);
- if (ts.isEntityName(node) || isImportType) {
- var isNamespaceName = ts.isModuleDeclaration(node.parent);
- if (isNamespaceName)
- isNewIdentifierLocation = true;
- var symbol = typeChecker.getSymbolAtLocation(node);
- if (symbol) {
- symbol = ts.skipAlias(symbol, typeChecker);
- if (symbol.flags & (1536 /* Module */ | 384 /* Enum */)) {
- // Extract module or enum members
- var exportedSymbols = typeChecker.getExportsOfModule(symbol);
- ts.Debug.assertEachIsDefined(exportedSymbols, "getExportsOfModule() should all be defined");
- var isValidValueAccess_1 = function (symbol) { return typeChecker.isValidPropertyAccess(isImportType ? node : (node.parent), symbol.name); };
- var isValidTypeAccess_1 = function (symbol) { return symbolCanBeReferencedAtTypeLocation(symbol); };
- var isValidAccess = isNamespaceName
- // At `namespace N.M/**/`, if this is the only declaration of `M`, don't include `M` as a completion.
- ? function (symbol) { return !!(symbol.flags & 1920 /* Namespace */) && !symbol.declarations.every(function (d) { return d.parent === node.parent; }); }
- : isRhsOfImportDeclaration ?
- // Any kind is allowed when dotting off namespace in internal import equals declaration
- function (symbol) { return isValidTypeAccess_1(symbol) || isValidValueAccess_1(symbol); } :
- isTypeLocation ? isValidTypeAccess_1 : isValidValueAccess_1;
- for (var _i = 0, exportedSymbols_1 = exportedSymbols; _i < exportedSymbols_1.length; _i++) {
- var exportedSymbol = exportedSymbols_1[_i];
- if (isValidAccess(exportedSymbol)) {
- symbols.push(exportedSymbol);
- }
- }
- // If the module is merged with a value, we must get the type of the class and add its propertes (for inherited static methods).
- if (!isTypeLocation &&
- symbol.declarations &&
- symbol.declarations.some(function (d) { return d.kind !== 290 /* SourceFile */ && d.kind !== 249 /* ModuleDeclaration */ && d.kind !== 248 /* EnumDeclaration */; })) {
- var type = typeChecker.getTypeOfSymbolAtLocation(symbol, node).getNonOptionalType();
- var insertQuestionDot = false;
- if (type.isNullableType()) {
- var canCorrectToQuestionDot = isRightOfDot &&
- !isRightOfQuestionDot &&
- preferences.includeAutomaticOptionalChainCompletions !== false;
- if (canCorrectToQuestionDot || isRightOfQuestionDot) {
- type = type.getNonNullableType();
- if (canCorrectToQuestionDot) {
- insertQuestionDot = true;
- }
- }
- }
- addTypeProperties(type, !!(node.flags & 32768 /* AwaitContext */), insertQuestionDot);
- }
- return;
- }
- }
- }
- if (ts.isMetaProperty(node) && (node.keywordToken === 99 /* NewKeyword */ || node.keywordToken === 96 /* ImportKeyword */) && contextToken === node.getChildAt(1)) {
- var completion = (node.keywordToken === 99 /* NewKeyword */) ? "target" : "meta";
- symbols.push(typeChecker.createSymbol(4 /* Property */, ts.escapeLeadingUnderscores(completion)));
- return;
- }
- if (!isTypeLocation) {
- var type = typeChecker.getTypeAtLocation(node).getNonOptionalType();
- var insertQuestionDot = false;
- if (type.isNullableType()) {
- var canCorrectToQuestionDot = isRightOfDot &&
- !isRightOfQuestionDot &&
- preferences.includeAutomaticOptionalChainCompletions !== false;
- if (canCorrectToQuestionDot || isRightOfQuestionDot) {
- type = type.getNonNullableType();
- if (canCorrectToQuestionDot) {
- insertQuestionDot = true;
- }
- }
- }
- addTypeProperties(type, !!(node.flags & 32768 /* AwaitContext */), insertQuestionDot);
- }
- }
- function addTypeProperties(type, insertAwait, insertQuestionDot) {
- isNewIdentifierLocation = !!type.getStringIndexType();
- if (isRightOfQuestionDot && ts.some(type.getCallSignatures())) {
- isNewIdentifierLocation = true;
- }
- var propertyAccess = node.kind === 188 /* ImportType */ ? node : node.parent;
- if (isUncheckedFile) {
- // In javascript files, for union types, we don't just get the members that
- // the individual types have in common, we also include all the members that
- // each individual type has. This is because we're going to add all identifiers
- // anyways. So we might as well elevate the members that were at least part
- // of the individual types to a higher status since we know what they are.
- symbols.push.apply(symbols, getPropertiesForCompletion(type, typeChecker));
- }
- else {
- for (var _i = 0, _a = type.getApparentProperties(); _i < _a.length; _i++) {
- var symbol = _a[_i];
- if (typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, symbol)) {
- addPropertySymbol(symbol, /*insertAwait*/ false, insertQuestionDot);
- }
- }
- }
- if (insertAwait && preferences.includeCompletionsWithInsertText) {
- var promiseType = typeChecker.getPromisedTypeOfPromise(type);
- if (promiseType) {
- for (var _b = 0, _c = promiseType.getApparentProperties(); _b < _c.length; _b++) {
- var symbol = _c[_b];
- if (typeChecker.isValidPropertyAccessForCompletions(propertyAccess, promiseType, symbol)) {
- addPropertySymbol(symbol, /* insertAwait */ true, insertQuestionDot);
- }
- }
- }
- }
- }
- function addPropertySymbol(symbol, insertAwait, insertQuestionDot) {
- // For a computed property with an accessible name like `Symbol.iterator`,
- // we'll add a completion for the *name* `Symbol` instead of for the property.
- // If this is e.g. [Symbol.iterator], add a completion for `Symbol`.
- var computedPropertyName = ts.firstDefined(symbol.declarations, function (decl) { return ts.tryCast(ts.getNameOfDeclaration(decl), ts.isComputedPropertyName); });
- if (computedPropertyName) {
- var leftMostName = getLeftMostName(computedPropertyName.expression); // The completion is for `Symbol`, not `iterator`.
- var nameSymbol = leftMostName && typeChecker.getSymbolAtLocation(leftMostName);
- // If this is nested like for `namespace N { export const sym = Symbol(); }`, we'll add the completion for `N`.
- var firstAccessibleSymbol = nameSymbol && getFirstSymbolInChain(nameSymbol, contextToken, typeChecker);
- if (firstAccessibleSymbol && !symbolToOriginInfoMap[ts.getSymbolId(firstAccessibleSymbol)]) {
- symbols.push(firstAccessibleSymbol);
- var moduleSymbol = firstAccessibleSymbol.parent;
- symbolToOriginInfoMap[ts.getSymbolId(firstAccessibleSymbol)] =
- !moduleSymbol || !ts.isExternalModuleSymbol(moduleSymbol)
- ? { kind: getNullableSymbolOriginInfoKind(2 /* SymbolMemberNoExport */) }
- : { kind: getNullableSymbolOriginInfoKind(6 /* SymbolMemberExport */), moduleSymbol: moduleSymbol, isDefaultExport: false };
- }
- else if (preferences.includeCompletionsWithInsertText) {
- addSymbolOriginInfo(symbol);
- symbols.push(symbol);
- }
- }
- else {
- addSymbolOriginInfo(symbol);
- symbols.push(symbol);
- }
- function addSymbolOriginInfo(symbol) {
- if (preferences.includeCompletionsWithInsertText) {
- if (insertAwait && !symbolToOriginInfoMap[ts.getSymbolId(symbol)]) {
- symbolToOriginInfoMap[ts.getSymbolId(symbol)] = { kind: getNullableSymbolOriginInfoKind(8 /* Promise */) };
- }
- else if (insertQuestionDot) {
- symbolToOriginInfoMap[ts.getSymbolId(symbol)] = { kind: 16 /* Nullable */ };
- }
- }
- }
- function getNullableSymbolOriginInfoKind(kind) {
- return insertQuestionDot ? kind | 16 /* Nullable */ : kind;
- }
- }
- /** Given 'a.b.c', returns 'a'. */
- function getLeftMostName(e) {
- return ts.isIdentifier(e) ? e : ts.isPropertyAccessExpression(e) ? getLeftMostName(e.expression) : undefined;
- }
- function tryGetGlobalSymbols() {
- var result = tryGetObjectLikeCompletionSymbols()
- || tryGetImportOrExportClauseCompletionSymbols()
- || tryGetLocalNamedExportCompletionSymbols()
- || tryGetConstructorCompletion()
- || tryGetClassLikeCompletionSymbols()
- || tryGetJsxCompletionSymbols()
- || (getGlobalCompletions(), 1 /* Success */);
- return result === 1 /* Success */;
- }
- function tryGetConstructorCompletion() {
- if (!tryGetConstructorLikeCompletionContainer(contextToken))
- return 0 /* Continue */;
- // no members, only keywords
- completionKind = 5 /* None */;
- // Declaring new property/method/accessor
- isNewIdentifierLocation = true;
- // Has keywords for constructor parameter
- keywordFilters = 4 /* ConstructorParameterKeywords */;
- return 1 /* Success */;
- }
- function tryGetJsxCompletionSymbols() {
- var jsxContainer = tryGetContainingJsxElement(contextToken);
- // Cursor is inside a JSX self-closing element or opening element
- var attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes);
- if (!attrsType)
- return 0 /* Continue */;
- var completionsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes, 4 /* Completions */);
- symbols = filterJsxAttributes(getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer.attributes, typeChecker), jsxContainer.attributes.properties);
- setSortTextToOptionalMember();
- completionKind = 3 /* MemberLike */;
- isNewIdentifierLocation = false;
- return 1 /* Success */;
- }
- function getGlobalCompletions() {
- keywordFilters = tryGetFunctionLikeBodyCompletionContainer(contextToken) ? 5 /* FunctionLikeBodyKeywords */ : 1 /* All */;
- // Get all entities in the current scope.
- completionKind = 1 /* Global */;
- isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken);
- if (previousToken !== contextToken) {
- ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'.");
- }
- // We need to find the node that will give us an appropriate scope to begin
- // aggregating completion candidates. This is achieved in 'getScopeNode'
- // by finding the first node that encompasses a position, accounting for whether a node
- // is "complete" to decide whether a position belongs to the node.
- //
- // However, at the end of an identifier, we are interested in the scope of the identifier
- // itself, but fall outside of the identifier. For instance:
- //
- // xyz => x$
- //
- // the cursor is outside of both the 'x' and the arrow function 'xyz => x',
- // so 'xyz' is not returned in our results.
- //
- // We define 'adjustedPosition' so that we may appropriately account for
- // being at the end of an identifier. The intention is that if requesting completion
- // at the end of an identifier, it should be effectively equivalent to requesting completion
- // anywhere inside/at the beginning of the identifier. So in the previous case, the
- // 'adjustedPosition' will work as if requesting completion in the following:
- //
- // xyz => $x
- //
- // If previousToken !== contextToken, then
- // - 'contextToken' was adjusted to the token prior to 'previousToken'
- // because we were at the end of an identifier.
- // - 'previousToken' is defined.
- var adjustedPosition = previousToken !== contextToken ?
- previousToken.getStart() :
- position;
- var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
- isInSnippetScope = isSnippetScope(scopeNode);
- var symbolMeanings = (isTypeOnly ? 0 /* None */ : 111551 /* Value */) | 788968 /* Type */ | 1920 /* Namespace */ | 2097152 /* Alias */;
- symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
- ts.Debug.assertEachIsDefined(symbols, "getSymbolsInScope() should all be defined");
- for (var _i = 0, symbols_2 = symbols; _i < symbols_2.length; _i++) {
- var symbol = symbols_2[_i];
- if (!typeChecker.isArgumentsSymbol(symbol) &&
- !ts.some(symbol.declarations, function (d) { return d.getSourceFile() === sourceFile; })) {
- symbolToSortTextMap[ts.getSymbolId(symbol)] = SortText.GlobalsOrKeywords;
- }
- }
- // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions`
- if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== 290 /* SourceFile */) {
- var thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false);
- if (thisType && !isProbablyGlobalType(thisType, sourceFile, typeChecker)) {
- for (var _a = 0, _b = getPropertiesForCompletion(thisType, typeChecker); _a < _b.length; _a++) {
- var symbol = _b[_a];
- symbolToOriginInfoMap[ts.getSymbolId(symbol)] = { kind: 1 /* ThisType */ };
- symbols.push(symbol);
- symbolToSortTextMap[ts.getSymbolId(symbol)] = SortText.SuggestedClassMembers;
- }
- }
- }
- if (shouldOfferImportCompletions()) {
- var lowerCaseTokenText_1 = previousToken && ts.isIdentifier(previousToken) ? previousToken.text.toLowerCase() : "";
- var autoImportSuggestions = getSymbolsFromOtherSourceFileExports(program.getCompilerOptions().target, host);
- if (!detailsEntryId && importSuggestionsCache) {
- importSuggestionsCache.set(sourceFile.fileName, autoImportSuggestions, host.getProjectVersion && host.getProjectVersion());
- }
- autoImportSuggestions.forEach(function (_a) {
- var symbol = _a.symbol, symbolName = _a.symbolName, skipFilter = _a.skipFilter, origin = _a.origin;
- if (detailsEntryId) {
- if (detailsEntryId.source && ts.stripQuotes(origin.moduleSymbol.name) !== detailsEntryId.source) {
- return;
- }
- }
- else if (!skipFilter && !stringContainsCharactersInOrder(symbolName.toLowerCase(), lowerCaseTokenText_1)) {
- return;
- }
- var symbolId = ts.getSymbolId(symbol);
- symbols.push(symbol);
- symbolToOriginInfoMap[symbolId] = origin;
- symbolToSortTextMap[symbolId] = SortText.AutoImportSuggestions;
- });
- }
- filterGlobalCompletion(symbols);
- }
- function shouldOfferImportCompletions() {
- // If not already a module, must have modules enabled.
- if (!preferences.includeCompletionsForModuleExports)
- return false;
- // If already using ES6 modules, OK to continue using them.
- if (sourceFile.externalModuleIndicator || sourceFile.commonJsModuleIndicator)
- return true;
- // If module transpilation is enabled or we're targeting es6 or above, or not emitting, OK.
- if (ts.compilerOptionsIndicateEs6Modules(program.getCompilerOptions()))
- return true;
- // If some file is using ES6 modules, assume that it's OK to add more.
- return ts.programContainsModules(program);
- }
- function isSnippetScope(scopeNode) {
- switch (scopeNode.kind) {
- case 290 /* SourceFile */:
- case 211 /* TemplateExpression */:
- case 276 /* JsxExpression */:
- case 223 /* Block */:
- return true;
- default:
- return ts.isStatement(scopeNode);
- }
- }
- function filterGlobalCompletion(symbols) {
- var isTypeOnly = isTypeOnlyCompletion();
- if (isTypeOnly) {
- keywordFilters = isTypeAssertion()
- ? 6 /* TypeAssertionKeywords */
- : 7 /* TypeKeywords */;
- }
- ts.filterMutate(symbols, function (symbol) {
- if (!ts.isSourceFile(location)) {
- // export = /**/ here we want to get all meanings, so any symbol is ok
- if (ts.isExportAssignment(location.parent)) {
- return true;
- }
- symbol = ts.skipAlias(symbol, typeChecker);
- // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
- if (ts.isInRightSideOfInternalImportEqualsDeclaration(location)) {
- return !!(symbol.flags & 1920 /* Namespace */);
- }
- if (isTypeOnly) {
- // It's a type, but you can reach it by namespace.type as well
- return symbolCanBeReferencedAtTypeLocation(symbol);
- }
- }
- // expressions are value space (which includes the value namespaces)
- return !!(ts.getCombinedLocalAndExportSymbolFlags(symbol) & 111551 /* Value */);
- });
- }
- function isTypeAssertion() {
- return ts.isAssertionExpression(contextToken.parent);
- }
- function isTypeOnlyCompletion() {
- return insideJsDocTagTypeExpression
- || !isContextTokenValueLocation(contextToken) &&
- (ts.isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker)
- || ts.isPartOfTypeNode(location)
- || isContextTokenTypeLocation(contextToken));
- }
- function isContextTokenValueLocation(contextToken) {
- return contextToken &&
- contextToken.kind === 108 /* TypeOfKeyword */ &&
- (contextToken.parent.kind === 172 /* TypeQuery */ || ts.isTypeOfExpression(contextToken.parent));
- }
- function isContextTokenTypeLocation(contextToken) {
- if (contextToken) {
- var parentKind = contextToken.parent.kind;
- switch (contextToken.kind) {
- case 58 /* ColonToken */:
- return parentKind === 159 /* PropertyDeclaration */ ||
- parentKind === 158 /* PropertySignature */ ||
- parentKind === 156 /* Parameter */ ||
- parentKind === 242 /* VariableDeclaration */ ||
- ts.isFunctionLikeKind(parentKind);
- case 62 /* EqualsToken */:
- return parentKind === 247 /* TypeAliasDeclaration */;
- case 123 /* AsKeyword */:
- return parentKind === 217 /* AsExpression */;
- case 29 /* LessThanToken */:
- return parentKind === 169 /* TypeReference */ ||
- parentKind === 199 /* TypeAssertionExpression */;
- case 90 /* ExtendsKeyword */:
- return parentKind === 155 /* TypeParameter */;
- }
- }
- return false;
- }
- /** True if symbol is a type or a module containing at least one type. */
- function symbolCanBeReferencedAtTypeLocation(symbol, seenModules) {
- if (seenModules === void 0) { seenModules = ts.createMap(); }
- var sym = ts.skipAlias(symbol.exportSymbol || symbol, typeChecker);
- return !!(sym.flags & 788968 /* Type */) ||
- !!(sym.flags & 1536 /* Module */) &&
- ts.addToSeen(seenModules, ts.getSymbolId(sym)) &&
- typeChecker.getExportsOfModule(sym).some(function (e) { return symbolCanBeReferencedAtTypeLocation(e, seenModules); });
- }
- /**
- * Gathers symbols that can be imported from other files, de-duplicating along the way. Symbols can be "duplicates"
- * if re-exported from another module, e.g. `export { foo } from "./a"`. That syntax creates a fresh symbol, but
- * it’s just an alias to the first, and both have the same name, so we generally want to filter those aliases out,
- * if and only if the the first can be imported (it may be excluded due to package.json filtering in
- * `codefix.forEachExternalModuleToImportFrom`).
- *
- * Example. Imagine a chain of node_modules re-exporting one original symbol:
- *
- * ```js
- * node_modules/x/index.js node_modules/y/index.js node_modules/z/index.js
- * +-----------------------+ +--------------------------+ +--------------------------+
- * | | | | | |
- * | export const foo = 0; | <--- | export { foo } from 'x'; | <--- | export { foo } from 'y'; |
- * | | | | | |
- * +-----------------------+ +--------------------------+ +--------------------------+
- * ```
- *
- * Also imagine three buckets, which we’ll reference soon:
- *
- * ```md
- * | | | | | |
- * | **Bucket A** | | **Bucket B** | | **Bucket C** |
- * | Symbols to | | Aliases to symbols | | Symbols to return |
- * | definitely | | in Buckets A or C | | if nothing better |
- * | return | | (don’t return these) | | comes along |
- * |__________________| |______________________| |___________________|
- * ```
- *
- * We _probably_ want to show `foo` from 'x', but not from 'y' or 'z'. However, if 'x' is not in a package.json, it
- * will not appear in a `forEachExternalModuleToImportFrom` iteration. Furthermore, the order of iterations is not
- * guaranteed, as it is host-dependent. Therefore, when presented with the symbol `foo` from module 'y' alone, we
- * may not be sure whether or not it should go in the list. So, we’ll take the following steps:
- *
- * 1. Resolve alias `foo` from 'y' to the export declaration in 'x', get the symbol there, and see if that symbol is
- * already in Bucket A (symbols we already know will be returned). If it is, put `foo` from 'y' in Bucket B
- * (symbols that are aliases to symbols in Bucket A). If it’s not, put it in Bucket C.
- * 2. Next, imagine we see `foo` from module 'z'. Again, we resolve the alias to the nearest export, which is in 'y'.
- * At this point, if that nearest export from 'y' is in _any_ of the three buckets, we know the symbol in 'z'
- * should never be returned in the final list, so put it in Bucket B.
- * 3. Next, imagine we see `foo` from module 'x', the original. Syntactically, it doesn’t look like a re-export, so
- * we can just check Bucket C to see if we put any aliases to the original in there. If they exist, throw them out.
- * Put this symbol in Bucket A.
- * 4. After we’ve iterated through every symbol of every module, any symbol left in Bucket C means that step 3 didn’t
- * occur for that symbol---that is, the original symbol is not in Bucket A, so we should include the alias. Move
- * everything from Bucket C to Bucket A.
- */
- function getSymbolsFromOtherSourceFileExports(target, host) {
- var cached = importSuggestionsCache && importSuggestionsCache.get(sourceFile.fileName, typeChecker, detailsEntryId && host.getProjectVersion ? host.getProjectVersion() : undefined);
- if (cached) {
- log("getSymbolsFromOtherSourceFileExports: Using cached list");
- return cached;
- }
- var startTime = ts.timestamp();
- log("getSymbolsFromOtherSourceFileExports: Recomputing list" + (detailsEntryId ? " for details entry" : ""));
- var seenResolvedModules = ts.createMap();
- var seenExports = ts.createMap();
- /** Bucket B */
- var aliasesToAlreadyIncludedSymbols = ts.createMap();
- /** Bucket C */
- var aliasesToReturnIfOriginalsAreMissing = ts.createMap();
- /** Bucket A */
- var results = [];
- /** Ids present in `results` for faster lookup */
- var resultSymbolIds = ts.createMap();
- ts.codefix.forEachExternalModuleToImportFrom(program, host, sourceFile, !detailsEntryId, function (moduleSymbol) {
- // Perf -- ignore other modules if this is a request for details
- if (detailsEntryId && detailsEntryId.source && ts.stripQuotes(moduleSymbol.name) !== detailsEntryId.source) {
- return;
- }
- var resolvedModuleSymbol = typeChecker.resolveExternalModuleSymbol(moduleSymbol);
- // resolvedModuleSymbol may be a namespace. A namespace may be `export =` by multiple module declarations, but only keep the first one.
- if (!ts.addToSeen(seenResolvedModules, ts.getSymbolId(resolvedModuleSymbol))) {
- return;
- }
- // Don't add another completion for `export =` of a symbol that's already global.
- // So in `declare namespace foo {} declare module "foo" { export = foo; }`, there will just be the global completion for `foo`.
- if (resolvedModuleSymbol !== moduleSymbol && ts.every(resolvedModuleSymbol.declarations, ts.isNonGlobalDeclaration)) {
- pushSymbol(resolvedModuleSymbol, moduleSymbol, /*skipFilter*/ true);
- }
- for (var _i = 0, _a = typeChecker.getExportsAndPropertiesOfModule(moduleSymbol); _i < _a.length; _i++) {
- var symbol = _a[_i];
- var symbolId = ts.getSymbolId(symbol).toString();
- // `getExportsAndPropertiesOfModule` can include duplicates
- if (!ts.addToSeen(seenExports, symbolId)) {
- continue;
- }
- // If this is `export { _break as break };` (a keyword) -- skip this and prefer the keyword completion.
- if (ts.some(symbol.declarations, function (d) { return ts.isExportSpecifier(d) && !!d.propertyName && ts.isIdentifierANonContextualKeyword(d.name); })) {
- continue;
- }
- // If `symbol.parent !== moduleSymbol`, this is an `export * from "foo"` re-export. Those don't create new symbols.
- var isExportStarFromReExport = typeChecker.getMergedSymbol(symbol.parent) !== resolvedModuleSymbol;
- // If `!!d.parent.parent.moduleSpecifier`, this is `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check).
- if (isExportStarFromReExport || ts.some(symbol.declarations, function (d) { return ts.isExportSpecifier(d) && !d.propertyName && !!d.parent.parent.moduleSpecifier; })) {
- // Walk the export chain back one module (step 1 or 2 in diagrammed example).
- // Or, in the case of `export * from "foo"`, `symbol` already points to the original export, so just use that.
- var nearestExportSymbol = isExportStarFromReExport ? symbol : getNearestExportSymbol(symbol);
- if (!nearestExportSymbol)
- continue;
- var nearestExportSymbolId = ts.getSymbolId(nearestExportSymbol).toString();
- var symbolHasBeenSeen = resultSymbolIds.has(nearestExportSymbolId) || aliasesToAlreadyIncludedSymbols.has(nearestExportSymbolId);
- if (!symbolHasBeenSeen) {
- aliasesToReturnIfOriginalsAreMissing.set(nearestExportSymbolId, { alias: symbol, moduleSymbol: moduleSymbol });
- aliasesToAlreadyIncludedSymbols.set(symbolId, true);
- }
- else {
- // Perf - we know this symbol is an alias to one that’s already covered in `symbols`, so store it here
- // in case another symbol re-exports this one; that way we can short-circuit as soon as we see this symbol id.
- ts.addToSeen(aliasesToAlreadyIncludedSymbols, symbolId);
- }
- }
- else {
- // This is not a re-export, so see if we have any aliases pending and remove them (step 3 in diagrammed example)
- aliasesToReturnIfOriginalsAreMissing.delete(symbolId);
- pushSymbol(symbol, moduleSymbol);
- }
- }
- });
- // By this point, any potential duplicates that were actually duplicates have been
- // removed, so the rest need to be added. (Step 4 in diagrammed example)
- aliasesToReturnIfOriginalsAreMissing.forEach(function (_a) {
- var alias = _a.alias, moduleSymbol = _a.moduleSymbol;
- return pushSymbol(alias, moduleSymbol);
- });
- log("getSymbolsFromOtherSourceFileExports: " + (ts.timestamp() - startTime));
- return results;
- function pushSymbol(symbol, moduleSymbol, skipFilter) {
- if (skipFilter === void 0) { skipFilter = false; }
- var isDefaultExport = symbol.escapedName === "default" /* Default */;
- if (isDefaultExport) {
- symbol = ts.getLocalSymbolForExportDefault(symbol) || symbol;
- }
- if (typeChecker.isUndefinedSymbol(symbol)) {
- return;
- }
- ts.addToSeen(resultSymbolIds, ts.getSymbolId(symbol));
- var origin = { kind: 4 /* Export */, moduleSymbol: moduleSymbol, isDefaultExport: isDefaultExport };
- results.push({
- symbol: symbol,
- symbolName: ts.getNameForExportedSymbol(symbol, target),
- origin: origin,
- skipFilter: skipFilter,
- });
- }
- }
- function getNearestExportSymbol(fromSymbol) {
- return findAlias(typeChecker, fromSymbol, function (alias) {
- return ts.some(alias.declarations, function (d) { return ts.isExportSpecifier(d) || !!d.localSymbol; });
- });
- }
- /**
- * True if you could remove some characters in `a` to get `b`.
- * E.g., true for "abcdef" and "bdf".
- * But not true for "abcdef" and "dbf".
- */
- function stringContainsCharactersInOrder(str, characters) {
- if (characters.length === 0) {
- return true;
- }
- var characterIndex = 0;
- for (var strIndex = 0; strIndex < str.length; strIndex++) {
- if (str.charCodeAt(strIndex) === characters.charCodeAt(characterIndex)) {
- characterIndex++;
- if (characterIndex === characters.length) {
- return true;
- }
- }
- }
- // Did not find all characters
- return false;
- }
- /**
- * Finds the first node that "embraces" the position, so that one may
- * accurately aggregate locals from the closest containing scope.
- */
- function getScopeNode(initialToken, position, sourceFile) {
- var scope = initialToken;
- while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) {
- scope = scope.parent;
- }
- return scope;
- }
- function isCompletionListBlocker(contextToken) {
- var start = ts.timestamp();
- var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) ||
- isSolelyIdentifierDefinitionLocation(contextToken) ||
- isDotOfNumericLiteral(contextToken) ||
- isInJsxText(contextToken);
- log("getCompletionsAtPosition: isCompletionListBlocker: " + (ts.timestamp() - start));
- return result;
- }
- function isInJsxText(contextToken) {
- if (contextToken.kind === 11 /* JsxText */) {
- return true;
- }
- if (contextToken.kind === 31 /* GreaterThanToken */ && contextToken.parent) {
- if (contextToken.parent.kind === 268 /* JsxOpeningElement */) {
- // Two possibilities:
- // 1.
/**/
- // - contextToken: GreaterThanToken (before cursor)
- // - location: JSXElement
- // - different parents (JSXOpeningElement, JSXElement)
- // 2. /**/>
- // - contextToken: GreaterThanToken (before cursor)
- // - location: GreaterThanToken (after cursor)
- // - same parent (JSXOpeningElement)
- return location.parent.kind !== 268 /* JsxOpeningElement */;
- }
- if (contextToken.parent.kind === 269 /* JsxClosingElement */ || contextToken.parent.kind === 267 /* JsxSelfClosingElement */) {
- return !!contextToken.parent.parent && contextToken.parent.parent.kind === 266 /* JsxElement */;
- }
- }
- return false;
- }
- function isNewIdentifierDefinitionLocation(previousToken) {
- if (previousToken) {
- var containingNodeKind = previousToken.parent.kind;
- // Previous token may have been a keyword that was converted to an identifier.
- switch (keywordForNode(previousToken)) {
- case 27 /* CommaToken */:
- return containingNodeKind === 196 /* CallExpression */ // func( a, |
- || containingNodeKind === 162 /* Constructor */ // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */
- || containingNodeKind === 197 /* NewExpression */ // new C(a, |
- || containingNodeKind === 192 /* ArrayLiteralExpression */ // [a, |
- || containingNodeKind === 209 /* BinaryExpression */ // const x = (a, |
- || containingNodeKind === 170 /* FunctionType */; // var x: (s: string, list|
- case 20 /* OpenParenToken */:
- return containingNodeKind === 196 /* CallExpression */ // func( |
- || containingNodeKind === 162 /* Constructor */ // constructor( |
- || containingNodeKind === 197 /* NewExpression */ // new C(a|
- || containingNodeKind === 200 /* ParenthesizedExpression */ // const x = (a|
- || containingNodeKind === 182 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */
- case 22 /* OpenBracketToken */:
- return containingNodeKind === 192 /* ArrayLiteralExpression */ // [ |
- || containingNodeKind === 167 /* IndexSignature */ // [ | : string ]
- || containingNodeKind === 154 /* ComputedPropertyName */; // [ | /* this can become an index signature */
- case 135 /* ModuleKeyword */: // module |
- case 136 /* NamespaceKeyword */: // namespace |
- return true;
- case 24 /* DotToken */:
- return containingNodeKind === 249 /* ModuleDeclaration */; // module A.|
- case 18 /* OpenBraceToken */:
- return containingNodeKind === 245 /* ClassDeclaration */; // class A{ |
- case 62 /* EqualsToken */:
- return containingNodeKind === 242 /* VariableDeclaration */ // const x = a|
- || containingNodeKind === 209 /* BinaryExpression */; // x = a|
- case 15 /* TemplateHead */:
- return containingNodeKind === 211 /* TemplateExpression */; // `aa ${|
- case 16 /* TemplateMiddle */:
- return containingNodeKind === 221 /* TemplateSpan */; // `aa ${10} dd ${|
- case 119 /* PublicKeyword */:
- case 117 /* PrivateKeyword */:
- case 118 /* ProtectedKeyword */:
- return containingNodeKind === 159 /* PropertyDeclaration */; // class A{ public |
- }
- }
- return false;
- }
- function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) {
- // To be "in" one of these literals, the position has to be:
- // 1. entirely within the token text.
- // 2. at the end position of an unterminated token.
- // 3. at the end of a regular expression (due to trailing flags like '/foo/g').
- return (ts.isRegularExpressionLiteral(contextToken) || ts.isStringTextContainingNode(contextToken)) && (ts.rangeContainsPositionExclusive(ts.createTextRangeFromSpan(ts.createTextSpanFromNode(contextToken)), position) ||
- position === contextToken.end && (!!contextToken.isUnterminated || ts.isRegularExpressionLiteral(contextToken)));
- }
- /**
- * Aggregates relevant symbols for completion in object literals and object binding patterns.
- * Relevant symbols are stored in the captured 'symbols' variable.
- *
- * @returns true if 'symbols' was successfully populated; false otherwise.
- */
- function tryGetObjectLikeCompletionSymbols() {
- var objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken);
- if (!objectLikeContainer)
- return 0 /* Continue */;
- // We're looking up possible property names from contextual/inferred/declared type.
- completionKind = 0 /* ObjectPropertyDeclaration */;
- var typeMembers;
- var existingMembers;
- if (objectLikeContainer.kind === 193 /* ObjectLiteralExpression */) {
- var instantiatedType = typeChecker.getContextualType(objectLikeContainer);
- var completionsType = instantiatedType && typeChecker.getContextualType(objectLikeContainer, 4 /* Completions */);
- if (!instantiatedType || !completionsType)
- return 2 /* Fail */;
- isNewIdentifierLocation = ts.hasIndexSignature(instantiatedType || completionsType);
- typeMembers = getPropertiesForObjectExpression(instantiatedType, completionsType, objectLikeContainer, typeChecker);
- existingMembers = objectLikeContainer.properties;
- }
- else {
- ts.Debug.assert(objectLikeContainer.kind === 189 /* ObjectBindingPattern */);
- // We are *only* completing on properties from the type being destructured.
- isNewIdentifierLocation = false;
- var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent);
- if (!ts.isVariableLike(rootDeclaration))
- return ts.Debug.fail("Root declaration is not variable-like.");
- // We don't want to complete using the type acquired by the shape
- // of the binding pattern; we are only interested in types acquired
- // through type declaration or inference.
- // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
- // type of parameter will flow in from the contextual type of the function
- var canGetType = ts.hasInitializer(rootDeclaration) || ts.hasType(rootDeclaration) || rootDeclaration.parent.parent.kind === 232 /* ForOfStatement */;
- if (!canGetType && rootDeclaration.kind === 156 /* Parameter */) {
- if (ts.isExpression(rootDeclaration.parent)) {
- canGetType = !!typeChecker.getContextualType(rootDeclaration.parent);
- }
- else if (rootDeclaration.parent.kind === 161 /* MethodDeclaration */ || rootDeclaration.parent.kind === 164 /* SetAccessor */) {
- canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent);
- }
- }
- if (canGetType) {
- var typeForObject_1 = typeChecker.getTypeAtLocation(objectLikeContainer);
- if (!typeForObject_1)
- return 2 /* Fail */;
- // In a binding pattern, get only known properties (unless in the same scope).
- // Everywhere else we will get all possible properties.
- var containerClass_1 = ts.getContainingClass(objectLikeContainer);
- typeMembers = typeChecker.getPropertiesOfType(typeForObject_1).filter(function (symbol) {
- // either public
- return !(ts.getDeclarationModifierFlagsFromSymbol(symbol) & 24 /* NonPublicAccessibilityModifier */)
- // or we're in it
- || containerClass_1 && ts.contains(typeForObject_1.symbol.declarations, containerClass_1);
- });
- existingMembers = objectLikeContainer.elements;
- }
- }
- if (typeMembers && typeMembers.length > 0) {
- // Add filtered items to the completion list
- symbols = filterObjectMembersList(typeMembers, ts.Debug.checkDefined(existingMembers));
- }
- setSortTextToOptionalMember();
- return 1 /* Success */;
- }
- /**
- * Aggregates relevant symbols for completion in import clauses and export clauses
- * whose declarations have a module specifier; for instance, symbols will be aggregated for
- *
- * import { | } from "moduleName";
- * export { a as foo, | } from "moduleName";
- *
- * but not for
- *
- * export { | };
- *
- * Relevant symbols are stored in the captured 'symbols' variable.
- */
- function tryGetImportOrExportClauseCompletionSymbols() {
- // `import { |` or `import { a as 0, | }`
- var namedImportsOrExports = contextToken && (contextToken.kind === 18 /* OpenBraceToken */ || contextToken.kind === 27 /* CommaToken */)
- ? ts.tryCast(contextToken.parent, ts.isNamedImportsOrExports) : undefined;
- if (!namedImportsOrExports)
- return 0 /* Continue */;
- // try to show exported member for imported/re-exported module
- var moduleSpecifier = (namedImportsOrExports.kind === 257 /* NamedImports */ ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent).moduleSpecifier;
- if (!moduleSpecifier)
- return namedImportsOrExports.kind === 257 /* NamedImports */ ? 2 /* Fail */ : 0 /* Continue */;
- var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); // TODO: GH#18217
- if (!moduleSpecifierSymbol)
- return 2 /* Fail */;
- completionKind = 3 /* MemberLike */;
- isNewIdentifierLocation = false;
- var exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol);
- var existing = ts.arrayToSet(namedImportsOrExports.elements, function (n) { return isCurrentlyEditingNode(n) ? undefined : (n.propertyName || n.name).escapedText; });
- symbols = exports.filter(function (e) { return e.escapedName !== "default" /* Default */ && !existing.get(e.escapedName); });
- return 1 /* Success */;
- }
- /**
- * Adds local declarations for completions in named exports:
- *
- * export { | };
- *
- * Does not check for the absence of a module specifier (`export {} from "./other"`)
- * because `tryGetImportOrExportClauseCompletionSymbols` runs first and handles that,
- * preventing this function from running.
- */
- function tryGetLocalNamedExportCompletionSymbols() {
- var _a;
- var namedExports = contextToken && (contextToken.kind === 18 /* OpenBraceToken */ || contextToken.kind === 27 /* CommaToken */)
- ? ts.tryCast(contextToken.parent, ts.isNamedExports)
- : undefined;
- if (!namedExports) {
- return 0 /* Continue */;
- }
- var localsContainer = ts.findAncestor(namedExports, ts.or(ts.isSourceFile, ts.isModuleDeclaration));
- completionKind = 5 /* None */;
- isNewIdentifierLocation = false;
- (_a = localsContainer.locals) === null || _a === void 0 ? void 0 : _a.forEach(function (symbol, name) {
- var _a, _b;
- symbols.push(symbol);
- if ((_b = (_a = localsContainer.symbol) === null || _a === void 0 ? void 0 : _a.exports) === null || _b === void 0 ? void 0 : _b.has(name)) {
- symbolToSortTextMap[ts.getSymbolId(symbol)] = SortText.OptionalMember;
- }
- });
- return 1 /* Success */;
- }
- /**
- * Aggregates relevant symbols for completion in class declaration
- * Relevant symbols are stored in the captured 'symbols' variable.
- */
- function tryGetClassLikeCompletionSymbols() {
- var decl = tryGetObjectTypeDeclarationCompletionContainer(sourceFile, contextToken, location, position);
- if (!decl)
- return 0 /* Continue */;
- // We're looking up possible property names from parent type.
- completionKind = 3 /* MemberLike */;
- // Declaring new property/method/accessor
- isNewIdentifierLocation = true;
- keywordFilters = contextToken.kind === 41 /* AsteriskToken */ ? 0 /* None */ :
- ts.isClassLike(decl) ? 2 /* ClassElementKeywords */ : 3 /* InterfaceElementKeywords */;
- // If you're in an interface you don't want to repeat things from super-interface. So just stop here.
- if (!ts.isClassLike(decl))
- return 1 /* Success */;
- var classElement = contextToken.kind === 26 /* SemicolonToken */ ? contextToken.parent.parent : contextToken.parent;
- var classElementModifierFlags = ts.isClassElement(classElement) ? ts.getModifierFlags(classElement) : 0 /* None */;
- // If this is context token is not something we are editing now, consider if this would lead to be modifier
- if (contextToken.kind === 75 /* Identifier */ && !isCurrentlyEditingNode(contextToken)) {
- switch (contextToken.getText()) {
- case "private":
- classElementModifierFlags = classElementModifierFlags | 8 /* Private */;
- break;
- case "static":
- classElementModifierFlags = classElementModifierFlags | 32 /* Static */;
- break;
- }
- }
- // No member list for private methods
- if (!(classElementModifierFlags & 8 /* Private */)) {
- // List of property symbols of base type that are not private and already implemented
- var baseSymbols = ts.flatMap(ts.getAllSuperTypeNodes(decl), function (baseTypeNode) {
- var type = typeChecker.getTypeAtLocation(baseTypeNode);
- return type && typeChecker.getPropertiesOfType(classElementModifierFlags & 32 /* Static */ ? typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl) : type);
- });
- symbols = filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags);
- }
- return 1 /* Success */;
- }
- /**
- * Returns the immediate owning object literal or binding pattern of a context token,
- * on the condition that one exists and that the context implies completion should be given.
- */
- function tryGetObjectLikeCompletionContainer(contextToken) {
- if (contextToken) {
- var parent = contextToken.parent;
- switch (contextToken.kind) {
- case 18 /* OpenBraceToken */: // const x = { |
- case 27 /* CommaToken */: // const x = { a: 0, |
- if (ts.isObjectLiteralExpression(parent) || ts.isObjectBindingPattern(parent)) {
- return parent;
- }
- break;
- case 41 /* AsteriskToken */:
- return ts.isMethodDeclaration(parent) ? ts.tryCast(parent.parent, ts.isObjectLiteralExpression) : undefined;
- case 75 /* Identifier */:
- return contextToken.text === "async" && ts.isShorthandPropertyAssignment(contextToken.parent)
- ? contextToken.parent.parent : undefined;
- }
- }
- return undefined;
- }
- function isConstructorParameterCompletion(node) {
- return !!node.parent && ts.isParameter(node.parent) && ts.isConstructorDeclaration(node.parent.parent)
- && (ts.isParameterPropertyModifier(node.kind) || ts.isDeclarationName(node));
- }
- /**
- * Returns the immediate owning class declaration of a context token,
- * on the condition that one exists and that the context implies completion should be given.
- */
- function tryGetConstructorLikeCompletionContainer(contextToken) {
- if (contextToken) {
- var parent = contextToken.parent;
- switch (contextToken.kind) {
- case 20 /* OpenParenToken */:
- case 27 /* CommaToken */:
- return ts.isConstructorDeclaration(contextToken.parent) ? contextToken.parent : undefined;
- default:
- if (isConstructorParameterCompletion(contextToken)) {
- return parent.parent;
- }
- }
- }
- return undefined;
- }
- function tryGetFunctionLikeBodyCompletionContainer(contextToken) {
- if (contextToken) {
- var prev_1;
- var container = ts.findAncestor(contextToken.parent, function (node) {
- if (ts.isClassLike(node)) {
- return "quit";
- }
- if (ts.isFunctionLikeDeclaration(node) && prev_1 === node.body) {
- return true;
- }
- prev_1 = node;
- return false;
- });
- return container && container;
- }
- }
- function tryGetContainingJsxElement(contextToken) {
- if (contextToken) {
- var parent = contextToken.parent;
- switch (contextToken.kind) {
- case 31 /* GreaterThanToken */: // End of a type argument list
- case 30 /* LessThanSlashToken */:
- case 43 /* SlashToken */:
- case 75 /* Identifier */:
- case 194 /* PropertyAccessExpression */:
- case 274 /* JsxAttributes */:
- case 273 /* JsxAttribute */:
- case 275 /* JsxSpreadAttribute */:
- if (parent && (parent.kind === 267 /* JsxSelfClosingElement */ || parent.kind === 268 /* JsxOpeningElement */)) {
- if (contextToken.kind === 31 /* GreaterThanToken */) {
- var precedingToken = ts.findPrecedingToken(contextToken.pos, sourceFile, /*startNode*/ undefined);
- if (!parent.typeArguments || (precedingToken && precedingToken.kind === 43 /* SlashToken */))
- break;
- }
- return parent;
- }
- else if (parent.kind === 273 /* JsxAttribute */) {
- // Currently we parse JsxOpeningLikeElement as:
- // JsxOpeningLikeElement
- // attributes: JsxAttributes
- // properties: NodeArray
- return parent.parent.parent;
- }
- break;
- // The context token is the closing } or " of an attribute, which means
- // its parent is a JsxExpression, whose parent is a JsxAttribute,
- // whose parent is a JsxOpeningLikeElement
- case 10 /* StringLiteral */:
- if (parent && ((parent.kind === 273 /* JsxAttribute */) || (parent.kind === 275 /* JsxSpreadAttribute */))) {
- // Currently we parse JsxOpeningLikeElement as:
- // JsxOpeningLikeElement
- // attributes: JsxAttributes
- // properties: NodeArray
- return parent.parent.parent;
- }
- break;
- case 19 /* CloseBraceToken */:
- if (parent &&
- parent.kind === 276 /* JsxExpression */ &&
- parent.parent && parent.parent.kind === 273 /* JsxAttribute */) {
- // Currently we parse JsxOpeningLikeElement as:
- // JsxOpeningLikeElement
- // attributes: JsxAttributes
- // properties: NodeArray
- // each JsxAttribute can have initializer as JsxExpression
- return parent.parent.parent.parent;
- }
- if (parent && parent.kind === 275 /* JsxSpreadAttribute */) {
- // Currently we parse JsxOpeningLikeElement as:
- // JsxOpeningLikeElement
- // attributes: JsxAttributes
- // properties: NodeArray
- return parent.parent.parent;
- }
- break;
- }
- }
- return undefined;
- }
- /**
- * @returns true if we are certain that the currently edited location must define a new location; false otherwise.
- */
- function isSolelyIdentifierDefinitionLocation(contextToken) {
- var parent = contextToken.parent;
- var containingNodeKind = parent.kind;
- switch (contextToken.kind) {
- case 27 /* CommaToken */:
- return containingNodeKind === 242 /* VariableDeclaration */ ||
- isVariableDeclarationListButNotTypeArgument(contextToken) ||
- containingNodeKind === 225 /* VariableStatement */ ||
- containingNodeKind === 248 /* EnumDeclaration */ || // enum a { foo, |
- isFunctionLikeButNotConstructor(containingNodeKind) ||
- containingNodeKind === 246 /* InterfaceDeclaration */ || // interface A= contextToken.pos);
- case 24 /* DotToken */:
- return containingNodeKind === 190 /* ArrayBindingPattern */; // var [.|
- case 58 /* ColonToken */:
- return containingNodeKind === 191 /* BindingElement */; // var {x :html|
- case 22 /* OpenBracketToken */:
- return containingNodeKind === 190 /* ArrayBindingPattern */; // var [x|
- case 20 /* OpenParenToken */:
- return containingNodeKind === 280 /* CatchClause */ ||
- isFunctionLikeButNotConstructor(containingNodeKind);
- case 18 /* OpenBraceToken */:
- return containingNodeKind === 248 /* EnumDeclaration */; // enum a { |
- case 29 /* LessThanToken */:
- return containingNodeKind === 245 /* ClassDeclaration */ || // class A< |
- containingNodeKind === 214 /* ClassExpression */ || // var C = class D< |
- containingNodeKind === 246 /* InterfaceDeclaration */ || // interface A< |
- containingNodeKind === 247 /* TypeAliasDeclaration */ || // type List< |
- ts.isFunctionLikeKind(containingNodeKind);
- case 120 /* StaticKeyword */:
- return containingNodeKind === 159 /* PropertyDeclaration */ && !ts.isClassLike(parent.parent);
- case 25 /* DotDotDotToken */:
- return containingNodeKind === 156 /* Parameter */ ||
- (!!parent.parent && parent.parent.kind === 190 /* ArrayBindingPattern */); // var [...z|
- case 119 /* PublicKeyword */:
- case 117 /* PrivateKeyword */:
- case 118 /* ProtectedKeyword */:
- return containingNodeKind === 156 /* Parameter */ && !ts.isConstructorDeclaration(parent.parent);
- case 123 /* AsKeyword */:
- return containingNodeKind === 258 /* ImportSpecifier */ ||
- containingNodeKind === 263 /* ExportSpecifier */ ||
- containingNodeKind === 256 /* NamespaceImport */;
- case 131 /* GetKeyword */:
- case 142 /* SetKeyword */:
- return !isFromObjectTypeDeclaration(contextToken);
- case 80 /* ClassKeyword */:
- case 88 /* EnumKeyword */:
- case 114 /* InterfaceKeyword */:
- case 94 /* FunctionKeyword */:
- case 109 /* VarKeyword */:
- case 96 /* ImportKeyword */:
- case 115 /* LetKeyword */:
- case 81 /* ConstKeyword */:
- case 145 /* TypeKeyword */: // type htm|
- return true;
- case 41 /* AsteriskToken */:
- return ts.isFunctionLike(contextToken.parent) && !ts.isMethodDeclaration(contextToken.parent);
- }
- // If the previous token is keyword correspoding to class member completion keyword
- // there will be completion available here
- if (isClassMemberCompletionKeyword(keywordForNode(contextToken)) && isFromObjectTypeDeclaration(contextToken)) {
- return false;
- }
- if (isConstructorParameterCompletion(contextToken)) {
- // constructor parameter completion is available only if
- // - its modifier of the constructor parameter or
- // - its name of the parameter and not being edited
- // eg. constructor(a |<- this shouldnt show completion
- if (!ts.isIdentifier(contextToken) ||
- ts.isParameterPropertyModifier(keywordForNode(contextToken)) ||
- isCurrentlyEditingNode(contextToken)) {
- return false;
- }
- }
- // Previous token may have been a keyword that was converted to an identifier.
- switch (keywordForNode(contextToken)) {
- case 122 /* AbstractKeyword */:
- case 80 /* ClassKeyword */:
- case 81 /* ConstKeyword */:
- case 130 /* DeclareKeyword */:
- case 88 /* EnumKeyword */:
- case 94 /* FunctionKeyword */:
- case 114 /* InterfaceKeyword */:
- case 115 /* LetKeyword */:
- case 117 /* PrivateKeyword */:
- case 118 /* ProtectedKeyword */:
- case 119 /* PublicKeyword */:
- case 120 /* StaticKeyword */:
- case 109 /* VarKeyword */:
- return true;
- case 126 /* AsyncKeyword */:
- return ts.isPropertyDeclaration(contextToken.parent);
- }
- return ts.isDeclarationName(contextToken)
- && !ts.isJsxAttribute(contextToken.parent)
- // Don't block completions if we're in `class C /**/`, because we're *past* the end of the identifier and might want to complete `extends`.
- // If `contextToken !== previousToken`, this is `class C ex/**/`.
- && !(ts.isClassLike(contextToken.parent) && (contextToken !== previousToken || position > previousToken.end));
- }
- function isFunctionLikeButNotConstructor(kind) {
- return ts.isFunctionLikeKind(kind) && kind !== 162 /* Constructor */;
- }
- function isDotOfNumericLiteral(contextToken) {
- if (contextToken.kind === 8 /* NumericLiteral */) {
- var text = contextToken.getFullText();
- return text.charAt(text.length - 1) === ".";
- }
- return false;
- }
- function isVariableDeclarationListButNotTypeArgument(node) {
- return node.parent.kind === 243 /* VariableDeclarationList */
- && !ts.isPossiblyTypeArgumentPosition(node, sourceFile, typeChecker);
- }
- /**
- * Filters out completion suggestions for named imports or exports.
- *
- * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations
- * do not occur at the current position and have not otherwise been typed.
- */
- function filterObjectMembersList(contextualMemberSymbols, existingMembers) {
- if (existingMembers.length === 0) {
- return contextualMemberSymbols;
- }
- var membersDeclaredBySpreadAssignment = ts.createMap();
- var existingMemberNames = ts.createUnderscoreEscapedMap();
- for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) {
- var m = existingMembers_1[_i];
- // Ignore omitted expressions for missing members
- if (m.kind !== 281 /* PropertyAssignment */ &&
- m.kind !== 282 /* ShorthandPropertyAssignment */ &&
- m.kind !== 191 /* BindingElement */ &&
- m.kind !== 161 /* MethodDeclaration */ &&
- m.kind !== 163 /* GetAccessor */ &&
- m.kind !== 164 /* SetAccessor */ &&
- m.kind !== 283 /* SpreadAssignment */) {
- continue;
- }
- // If this is the current item we are editing right now, do not filter it out
- if (isCurrentlyEditingNode(m)) {
- continue;
- }
- var existingName = void 0;
- if (ts.isSpreadAssignment(m)) {
- setMembersDeclaredBySpreadAssignment(m, membersDeclaredBySpreadAssignment);
- }
- else if (ts.isBindingElement(m) && m.propertyName) {
- // include only identifiers in completion list
- if (m.propertyName.kind === 75 /* Identifier */) {
- existingName = m.propertyName.escapedText;
- }
- }
- else {
- // TODO: Account for computed property name
- // NOTE: if one only performs this step when m.name is an identifier,
- // things like '__proto__' are not filtered out.
- var name = ts.getNameOfDeclaration(m);
- existingName = name && ts.isPropertyNameLiteral(name) ? ts.getEscapedTextOfIdentifierOrLiteral(name) : undefined;
- }
- existingMemberNames.set(existingName, true); // TODO: GH#18217
- }
- var filteredSymbols = contextualMemberSymbols.filter(function (m) { return !existingMemberNames.get(m.escapedName); });
- setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, filteredSymbols);
- return filteredSymbols;
- }
- function setMembersDeclaredBySpreadAssignment(declaration, membersDeclaredBySpreadAssignment) {
- var expression = declaration.expression;
- var symbol = typeChecker.getSymbolAtLocation(expression);
- var type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, expression);
- var properties = type && type.properties;
- if (properties) {
- properties.forEach(function (property) {
- membersDeclaredBySpreadAssignment.set(property.name, true);
- });
- }
- }
- // Set SortText to OptionalMember if it is an optional member
- function setSortTextToOptionalMember() {
- symbols.forEach(function (m) {
- if (m.flags & 16777216 /* Optional */) {
- symbolToSortTextMap[ts.getSymbolId(m)] = symbolToSortTextMap[ts.getSymbolId(m)] || SortText.OptionalMember;
- }
- });
- }
- // Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment
- function setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, contextualMemberSymbols) {
- if (membersDeclaredBySpreadAssignment.size === 0) {
- return;
- }
- for (var _i = 0, contextualMemberSymbols_1 = contextualMemberSymbols; _i < contextualMemberSymbols_1.length; _i++) {
- var contextualMemberSymbol = contextualMemberSymbols_1[_i];
- if (membersDeclaredBySpreadAssignment.has(contextualMemberSymbol.name)) {
- symbolToSortTextMap[ts.getSymbolId(contextualMemberSymbol)] = SortText.MemberDeclaredBySpreadAssignment;
- }
- }
- }
- /**
- * Filters out completion suggestions for class elements.
- *
- * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags
- */
- function filterClassMembersList(baseSymbols, existingMembers, currentClassElementModifierFlags) {
- var existingMemberNames = ts.createUnderscoreEscapedMap();
- for (var _i = 0, existingMembers_2 = existingMembers; _i < existingMembers_2.length; _i++) {
- var m = existingMembers_2[_i];
- // Ignore omitted expressions for missing members
- if (m.kind !== 159 /* PropertyDeclaration */ &&
- m.kind !== 161 /* MethodDeclaration */ &&
- m.kind !== 163 /* GetAccessor */ &&
- m.kind !== 164 /* SetAccessor */) {
- continue;
- }
- // If this is the current item we are editing right now, do not filter it out
- if (isCurrentlyEditingNode(m)) {
- continue;
- }
- // Dont filter member even if the name matches if it is declared private in the list
- if (ts.hasModifier(m, 8 /* Private */)) {
- continue;
- }
- // do not filter it out if the static presence doesnt match
- if (ts.hasModifier(m, 32 /* Static */) !== !!(currentClassElementModifierFlags & 32 /* Static */)) {
- continue;
- }
- var existingName = ts.getPropertyNameForPropertyNameNode(m.name);
- if (existingName) {
- existingMemberNames.set(existingName, true);
- }
- }
- return baseSymbols.filter(function (propertySymbol) {
- return !existingMemberNames.has(propertySymbol.escapedName) &&
- !!propertySymbol.declarations &&
- !(ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & 8 /* Private */) &&
- !ts.isPrivateIdentifierPropertyDeclaration(propertySymbol.valueDeclaration);
- });
- }
- /**
- * Filters out completion suggestions from 'symbols' according to existing JSX attributes.
- *
- * @returns Symbols to be suggested in a JSX element, barring those whose attributes
- * do not occur at the current position and have not otherwise been typed.
- */
- function filterJsxAttributes(symbols, attributes) {
- var seenNames = ts.createUnderscoreEscapedMap();
- var membersDeclaredBySpreadAssignment = ts.createMap();
- for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) {
- var attr = attributes_1[_i];
- // If this is the current item we are editing right now, do not filter it out
- if (isCurrentlyEditingNode(attr)) {
- continue;
- }
- if (attr.kind === 273 /* JsxAttribute */) {
- seenNames.set(attr.name.escapedText, true);
- }
- else if (ts.isJsxSpreadAttribute(attr)) {
- setMembersDeclaredBySpreadAssignment(attr, membersDeclaredBySpreadAssignment);
- }
- }
- var filteredSymbols = symbols.filter(function (a) { return !seenNames.get(a.escapedName); });
- setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, filteredSymbols);
- return filteredSymbols;
- }
- function isCurrentlyEditingNode(node) {
- return node.getStart(sourceFile) <= position && position <= node.getEnd();
- }
- }
- function getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind, jsxIdentifierExpected) {
- var name = originIsExport(origin) ? ts.getNameForExportedSymbol(symbol, target) : symbol.name;
- if (name === undefined
- // If the symbol is external module, don't show it in the completion list
- // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there)
- || symbol.flags & 1536 /* Module */ && ts.isSingleOrDoubleQuote(name.charCodeAt(0))
- // If the symbol is the internal name of an ES symbol, it is not a valid entry. Internal names for ES symbols start with "__@"
- || ts.isKnownSymbol(symbol)) {
- return undefined;
- }
- var validNameResult = { name: name, needsConvertPropertyAccess: false };
- if (ts.isIdentifierText(name, target, jsxIdentifierExpected ? 1 /* JSX */ : 0 /* Standard */) || symbol.valueDeclaration && ts.isPrivateIdentifierPropertyDeclaration(symbol.valueDeclaration)) {
- return validNameResult;
- }
- switch (kind) {
- case 3 /* MemberLike */:
- return undefined;
- case 0 /* ObjectPropertyDeclaration */:
- // TODO: GH#18169
- return { name: JSON.stringify(name), needsConvertPropertyAccess: false };
- case 2 /* PropertyAccess */:
- case 1 /* Global */: // For a 'this.' completion it will be in a global context, but may have a non-identifier name.
- // Don't add a completion for a name starting with a space. See https://github.com/Microsoft/TypeScript/pull/20547
- return name.charCodeAt(0) === 32 /* space */ ? undefined : { name: name, needsConvertPropertyAccess: true };
- case 5 /* None */:
- case 4 /* String */:
- return validNameResult;
- default:
- ts.Debug.assertNever(kind);
- }
- }
- // A cache of completion entries for keywords, these do not change between sessions
- var _keywordCompletions = [];
- var allKeywordsCompletions = ts.memoize(function () {
- var res = [];
- for (var i = 77 /* FirstKeyword */; i <= 152 /* LastKeyword */; i++) {
- res.push({
- name: ts.tokenToString(i),
- kind: "keyword" /* keyword */,
- kindModifiers: "" /* none */,
- sortText: SortText.GlobalsOrKeywords
- });
- }
- return res;
- });
- function getKeywordCompletions(keywordFilter, filterOutTsOnlyKeywords) {
- if (!filterOutTsOnlyKeywords)
- return getTypescriptKeywordCompletions(keywordFilter);
- var index = keywordFilter + 7 /* Last */ + 1;
- return _keywordCompletions[index] ||
- (_keywordCompletions[index] = getTypescriptKeywordCompletions(keywordFilter)
- .filter(function (entry) { return !isTypeScriptOnlyKeyword(ts.stringToToken(entry.name)); }));
- }
- function getTypescriptKeywordCompletions(keywordFilter) {
- return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(function (entry) {
- var kind = ts.stringToToken(entry.name);
- switch (keywordFilter) {
- case 0 /* None */:
- return false;
- case 1 /* All */:
- return isFunctionLikeBodyKeyword(kind)
- || kind === 130 /* DeclareKeyword */
- || kind === 135 /* ModuleKeyword */
- || kind === 145 /* TypeKeyword */
- || kind === 136 /* NamespaceKeyword */
- || kind === 123 /* AsKeyword */
- || ts.isTypeKeyword(kind) && kind !== 146 /* UndefinedKeyword */;
- case 5 /* FunctionLikeBodyKeywords */:
- return isFunctionLikeBodyKeyword(kind);
- case 2 /* ClassElementKeywords */:
- return isClassMemberCompletionKeyword(kind);
- case 3 /* InterfaceElementKeywords */:
- return isInterfaceOrTypeLiteralCompletionKeyword(kind);
- case 4 /* ConstructorParameterKeywords */:
- return ts.isParameterPropertyModifier(kind);
- case 6 /* TypeAssertionKeywords */:
- return ts.isTypeKeyword(kind) || kind === 81 /* ConstKeyword */;
- case 7 /* TypeKeywords */:
- return ts.isTypeKeyword(kind);
- default:
- return ts.Debug.assertNever(keywordFilter);
- }
- }));
- }
- function isTypeScriptOnlyKeyword(kind) {
- switch (kind) {
- case 122 /* AbstractKeyword */:
- case 125 /* AnyKeyword */:
- case 151 /* BigIntKeyword */:
- case 128 /* BooleanKeyword */:
- case 130 /* DeclareKeyword */:
- case 88 /* EnumKeyword */:
- case 150 /* GlobalKeyword */:
- case 113 /* ImplementsKeyword */:
- case 132 /* InferKeyword */:
- case 114 /* InterfaceKeyword */:
- case 133 /* IsKeyword */:
- case 134 /* KeyOfKeyword */:
- case 135 /* ModuleKeyword */:
- case 136 /* NamespaceKeyword */:
- case 137 /* NeverKeyword */:
- case 140 /* NumberKeyword */:
- case 141 /* ObjectKeyword */:
- case 117 /* PrivateKeyword */:
- case 118 /* ProtectedKeyword */:
- case 119 /* PublicKeyword */:
- case 138 /* ReadonlyKeyword */:
- case 143 /* StringKeyword */:
- case 144 /* SymbolKeyword */:
- case 145 /* TypeKeyword */:
- case 147 /* UniqueKeyword */:
- case 148 /* UnknownKeyword */:
- return true;
- default:
- return false;
- }
- }
- function isInterfaceOrTypeLiteralCompletionKeyword(kind) {
- return kind === 138 /* ReadonlyKeyword */;
- }
- function isClassMemberCompletionKeyword(kind) {
- switch (kind) {
- case 122 /* AbstractKeyword */:
- case 129 /* ConstructorKeyword */:
- case 131 /* GetKeyword */:
- case 142 /* SetKeyword */:
- case 126 /* AsyncKeyword */:
- case 130 /* DeclareKeyword */:
- return true;
- default:
- return ts.isClassMemberModifier(kind);
- }
- }
- function isFunctionLikeBodyKeyword(kind) {
- return kind === 126 /* AsyncKeyword */
- || kind === 127 /* AwaitKeyword */
- || !ts.isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
- }
- function keywordForNode(node) {
- return ts.isIdentifier(node) ? node.originalKeywordKind || 0 /* Unknown */ : node.kind;
- }
- /** Get the corresponding JSDocTag node if the position is in a jsDoc comment */
- function getJsDocTagAtPosition(node, position) {
- var jsdoc = ts.findAncestor(node, ts.isJSDoc);
- return jsdoc && jsdoc.tags && (ts.rangeContainsPosition(jsdoc, position) ? ts.findLast(jsdoc.tags, function (tag) { return tag.pos < position; }) : undefined);
- }
- function getPropertiesForObjectExpression(contextualType, completionsType, obj, checker) {
- var hasCompletionsType = completionsType && completionsType !== contextualType;
- var type = hasCompletionsType && !(completionsType.flags & 3 /* AnyOrUnknown */)
- ? checker.getUnionType([contextualType, completionsType])
- : contextualType;
- var properties = type.isUnion()
- ? checker.getAllPossiblePropertiesOfTypes(type.types.filter(function (memberType) {
- // If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals.
- return !(memberType.flags & 131068 /* Primitive */ ||
- checker.isArrayLikeType(memberType) ||
- ts.typeHasCallOrConstructSignatures(memberType, checker) ||
- checker.isTypeInvalidDueToUnionDiscriminant(memberType, obj));
- }))
- : type.getApparentProperties();
- return hasCompletionsType ? properties.filter(hasDeclarationOtherThanSelf) : properties;
- // Filter out members whose only declaration is the object literal itself to avoid
- // self-fulfilling completions like:
- //
- // function f(x: T) {}
- // f({ abc/**/: "" }) // `abc` is a member of `T` but only because it declares itself
- function hasDeclarationOtherThanSelf(member) {
- return ts.some(member.declarations, function (decl) { return decl.parent !== obj; });
- }
- }
- /**
- * Gets all properties on a type, but if that type is a union of several types,
- * excludes array-like types or callable/constructable types.
- */
- function getPropertiesForCompletion(type, checker) {
- return type.isUnion()
- ? ts.Debug.checkEachDefined(checker.getAllPossiblePropertiesOfTypes(type.types), "getAllPossiblePropertiesOfTypes() should all be defined")
- : ts.Debug.checkEachDefined(type.getApparentProperties(), "getApparentProperties() should all be defined");
- }
- /**
- * Returns the immediate owning class declaration of a context token,
- * on the condition that one exists and that the context implies completion should be given.
- */
- function tryGetObjectTypeDeclarationCompletionContainer(sourceFile, contextToken, location, position) {
- // class c { method() { } | method2() { } }
- switch (location.kind) {
- case 324 /* SyntaxList */:
- return ts.tryCast(location.parent, ts.isObjectTypeDeclaration);
- case 1 /* EndOfFileToken */:
- var cls = ts.tryCast(ts.lastOrUndefined(ts.cast(location.parent, ts.isSourceFile).statements), ts.isObjectTypeDeclaration);
- if (cls && !ts.findChildOfKind(cls, 19 /* CloseBraceToken */, sourceFile)) {
- return cls;
- }
- break;
- case 75 /* Identifier */: {
- // class c { public prop = c| }
- if (ts.isPropertyDeclaration(location.parent) && location.parent.initializer === location) {
- return undefined;
- }
- // class c extends React.Component { a: () => 1\n compon| }
- if (isFromObjectTypeDeclaration(location)) {
- return ts.findAncestor(location, ts.isObjectTypeDeclaration);
- }
- }
- }
- if (!contextToken)
- return undefined;
- switch (contextToken.kind) {
- case 62 /* EqualsToken */: // class c { public prop = | /* global completions */ }
- return undefined;
- case 26 /* SemicolonToken */: // class c {getValue(): number; | }
- case 19 /* CloseBraceToken */: // class c { method() { } | }
- // class c { method() { } b| }
- return isFromObjectTypeDeclaration(location) && location.parent.name === location
- ? location.parent.parent
- : ts.tryCast(location, ts.isObjectTypeDeclaration);
- case 18 /* OpenBraceToken */: // class c { |
- case 27 /* CommaToken */: // class c {getValue(): number, | }
- return ts.tryCast(contextToken.parent, ts.isObjectTypeDeclaration);
- default:
- if (!isFromObjectTypeDeclaration(contextToken)) {
- // class c extends React.Component { a: () => 1\n| }
- if (ts.getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== ts.getLineAndCharacterOfPosition(sourceFile, position).line && ts.isObjectTypeDeclaration(location)) {
- return location;
- }
- return undefined;
- }
- var isValidKeyword = ts.isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword;
- return (isValidKeyword(contextToken.kind) || contextToken.kind === 41 /* AsteriskToken */ || ts.isIdentifier(contextToken) && isValidKeyword(ts.stringToToken(contextToken.text))) // TODO: GH#18217
- ? contextToken.parent.parent : undefined;
- }
- }
- // TODO: GH#19856 Would like to return `node is Node & { parent: (ClassElement | TypeElement) & { parent: ObjectTypeDeclaration } }` but then compilation takes > 10 minutes
- function isFromObjectTypeDeclaration(node) {
- return node.parent && ts.isClassOrTypeElement(node.parent) && ts.isObjectTypeDeclaration(node.parent.parent);
- }
- function isValidTrigger(sourceFile, triggerCharacter, contextToken, position) {
- switch (triggerCharacter) {
- case ".":
- case "@":
- return true;
- case '"':
- case "'":
- case "`":
- // Only automatically bring up completions if this is an opening quote.
- return !!contextToken && ts.isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1;
- case "#":
- return !!contextToken && ts.isPrivateIdentifier(contextToken) && !!ts.getContainingClass(contextToken);
- case "<":
- // Opening JSX tag
- return !!contextToken && contextToken.kind === 29 /* LessThanToken */ && (!ts.isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent));
- case "/":
- return !!contextToken && (ts.isStringLiteralLike(contextToken)
- ? !!ts.tryGetImportFromModuleSpecifier(contextToken)
- : contextToken.kind === 43 /* SlashToken */ && ts.isJsxClosingElement(contextToken.parent));
- default:
- return ts.Debug.assertNever(triggerCharacter);
- }
- }
- function binaryExpressionMayBeOpenTag(_a) {
- var left = _a.left;
- return ts.nodeIsMissing(left);
- }
- function findAlias(typeChecker, symbol, predicate) {
- var currentAlias = symbol;
- while (currentAlias.flags & 2097152 /* Alias */ && (currentAlias = typeChecker.getImmediateAliasedSymbol(currentAlias))) {
- if (predicate(currentAlias)) {
- return currentAlias;
- }
- }
- }
- /** Determines if a type is exactly the same type resolved by the global 'self', 'global', or 'globalThis'. */
- function isProbablyGlobalType(type, sourceFile, checker) {
- // The type of `self` and `window` is the same in lib.dom.d.ts, but `window` does not exist in
- // lib.webworker.d.ts, so checking against `self` is also a check against `window` when it exists.
- var selfSymbol = checker.resolveName("self", /*location*/ undefined, 111551 /* Value */, /*excludeGlobals*/ false);
- if (selfSymbol && checker.getTypeOfSymbolAtLocation(selfSymbol, sourceFile) === type) {
- return true;
- }
- var globalSymbol = checker.resolveName("global", /*location*/ undefined, 111551 /* Value */, /*excludeGlobals*/ false);
- if (globalSymbol && checker.getTypeOfSymbolAtLocation(globalSymbol, sourceFile) === type) {
- return true;
- }
- var globalThisSymbol = checker.resolveName("globalThis", /*location*/ undefined, 111551 /* Value */, /*excludeGlobals*/ false);
- if (globalThisSymbol && checker.getTypeOfSymbolAtLocation(globalThisSymbol, sourceFile) === type) {
- return true;
- }
- return false;
- }
- })(Completions = ts.Completions || (ts.Completions = {}));
-})(ts || (ts = {}));
-var ts;
-(function (ts) {
- /* @internal */
- var DocumentHighlights;
- (function (DocumentHighlights) {
- function getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch) {
- var node = ts.getTouchingPropertyName(sourceFile, position);
- if (node.parent && (ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node || ts.isJsxClosingElement(node.parent))) {
- // For a JSX element, just highlight the matching tag, not all references.
- var _a = node.parent.parent, openingElement = _a.openingElement, closingElement = _a.closingElement;
- var highlightSpans = [openingElement, closingElement].map(function (_a) {
- var tagName = _a.tagName;
- return getHighlightSpanForNode(tagName, sourceFile);
- });
- return [{ fileName: sourceFile.fileName, highlightSpans: highlightSpans }];
- }
- return getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile);
- }
- DocumentHighlights.getDocumentHighlights = getDocumentHighlights;
- function getHighlightSpanForNode(node, sourceFile) {
- return {
- fileName: sourceFile.fileName,
- textSpan: ts.createTextSpanFromNode(node, sourceFile),
- kind: "none" /* none */
- };
- }
- function getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) {
- var sourceFilesSet = ts.arrayToSet(sourceFilesToSearch, function (f) { return f.fileName; });
- var referenceEntries = ts.FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken, /*options*/ undefined, sourceFilesSet);
- if (!referenceEntries)
- return undefined;
- var map = ts.arrayToMultiMap(referenceEntries.map(ts.FindAllReferences.toHighlightSpan), function (e) { return e.fileName; }, function (e) { return e.span; });
- return ts.arrayFrom(map.entries(), function (_a) {
- var fileName = _a[0], highlightSpans = _a[1];
- if (!sourceFilesSet.has(fileName)) {
- ts.Debug.assert(program.redirectTargetsMap.has(fileName));
- var redirectTarget_1 = program.getSourceFile(fileName);
- var redirect = ts.find(sourceFilesToSearch, function (f) { return !!f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget_1; });
- fileName = redirect.fileName;
- ts.Debug.assert(sourceFilesSet.has(fileName));
- }
- return { fileName: fileName, highlightSpans: highlightSpans };
- });
- }
- function getSyntacticDocumentHighlights(node, sourceFile) {
- var highlightSpans = getHighlightSpans(node, sourceFile);
- return highlightSpans && [{ fileName: sourceFile.fileName, highlightSpans: highlightSpans }];
- }
- function getHighlightSpans(node, sourceFile) {
- switch (node.kind) {
- case 95 /* IfKeyword */:
- case 87 /* ElseKeyword */:
- return ts.isIfStatement(node.parent) ? getIfElseOccurrences(node.parent, sourceFile) : undefined;
- case 101 /* ReturnKeyword */:
- return useParent(node.parent, ts.isReturnStatement, getReturnOccurrences);
- case 105 /* ThrowKeyword */:
- return useParent(node.parent, ts.isThrowStatement, getThrowOccurrences);
- case 107 /* TryKeyword */:
- case 79 /* CatchKeyword */:
- case 92 /* FinallyKeyword */:
- var tryStatement = node.kind === 79 /* CatchKeyword */ ? node.parent.parent : node.parent;
- return useParent(tryStatement, ts.isTryStatement, getTryCatchFinallyOccurrences);
- case 103 /* SwitchKeyword */:
- return useParent(node.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences);
- case 78 /* CaseKeyword */:
- case 84 /* DefaultKeyword */: {
- if (ts.isDefaultClause(node.parent) || ts.isCaseClause(node.parent)) {
- return useParent(node.parent.parent.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences);
- }
- return undefined;
- }
- case 77 /* BreakKeyword */:
- case 82 /* ContinueKeyword */:
- return useParent(node.parent, ts.isBreakOrContinueStatement, getBreakOrContinueStatementOccurrences);
- case 93 /* ForKeyword */:
- case 111 /* WhileKeyword */:
- case 86 /* DoKeyword */:
- return useParent(node.parent, function (n) { return ts.isIterationStatement(n, /*lookInLabeledStatements*/ true); }, getLoopBreakContinueOccurrences);
- case 129 /* ConstructorKeyword */:
- return getFromAllDeclarations(ts.isConstructorDeclaration, [129 /* ConstructorKeyword */]);
- case 131 /* GetKeyword */:
- case 142 /* SetKeyword */:
- return getFromAllDeclarations(ts.isAccessor, [131 /* GetKeyword */, 142 /* SetKeyword */]);
- case 127 /* AwaitKeyword */:
- return useParent(node.parent, ts.isAwaitExpression, getAsyncAndAwaitOccurrences);
- case 126 /* AsyncKeyword */:
- return highlightSpans(getAsyncAndAwaitOccurrences(node));
- case 121 /* YieldKeyword */:
- return highlightSpans(getYieldOccurrences(node));
- default:
- return ts.isModifierKind(node.kind) && (ts.isDeclaration(node.parent) || ts.isVariableStatement(node.parent))
- ? highlightSpans(getModifierOccurrences(node.kind, node.parent))
- : undefined;
- }
- function getFromAllDeclarations(nodeTest, keywords) {
- return useParent(node.parent, nodeTest, function (decl) { return ts.mapDefined(decl.symbol.declarations, function (d) {
- return nodeTest(d) ? ts.find(d.getChildren(sourceFile), function (c) { return ts.contains(keywords, c.kind); }) : undefined;
- }); });
- }
- function useParent(node, nodeTest, getNodes) {
- return nodeTest(node) ? highlightSpans(getNodes(node, sourceFile)) : undefined;
- }
- function highlightSpans(nodes) {
- return nodes && nodes.map(function (node) { return getHighlightSpanForNode(node, sourceFile); });
- }
- }
- /**
- * Aggregates all throw-statements within this node *without* crossing
- * into function boundaries and try-blocks with catch-clauses.
- */
- function aggregateOwnedThrowStatements(node) {
- if (ts.isThrowStatement(node)) {
- return [node];
- }
- else if (ts.isTryStatement(node)) {
- // Exceptions thrown within a try block lacking a catch clause are "owned" in the current context.
- return ts.concatenate(node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock), node.finallyBlock && aggregateOwnedThrowStatements(node.finallyBlock));
- }
- // Do not cross function boundaries.
- return ts.isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateOwnedThrowStatements);
- }
- /**
- * For lack of a better name, this function takes a throw statement and returns the
- * nearest ancestor that is a try-block (whose try statement has a catch clause),
- * function-block, or source file.
- */
- function getThrowStatementOwner(throwStatement) {
- var child = throwStatement;
- while (child.parent) {
- var parent = child.parent;
- if (ts.isFunctionBlock(parent) || parent.kind === 290 /* SourceFile */) {
- return parent;
- }
- // A throw-statement is only owned by a try-statement if the try-statement has
- // a catch clause, and if the throw-statement occurs within the try block.
- if (ts.isTryStatement(parent) && parent.tryBlock === child && parent.catchClause) {
- return child;
- }
- child = parent;
- }
- return undefined;
- }
- function aggregateAllBreakAndContinueStatements(node) {
- return ts.isBreakOrContinueStatement(node) ? [node] : ts.isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateAllBreakAndContinueStatements);
- }
- function flatMapChildren(node, cb) {
- var result = [];
- node.forEachChild(function (child) {
- var value = cb(child);
- if (value !== undefined) {
- result.push.apply(result, ts.toArray(value));
- }
- });
- return result;
- }
- function ownsBreakOrContinueStatement(owner, statement) {
- var actualOwner = getBreakOrContinueOwner(statement);
- return !!actualOwner && actualOwner === owner;
- }
- function getBreakOrContinueOwner(statement) {
- return ts.findAncestor(statement, function (node) {
- switch (node.kind) {
- case 237 /* SwitchStatement */:
- if (statement.kind === 233 /* ContinueStatement */) {
- return false;
- }
- // falls through
- case 230 /* ForStatement */:
- case 231 /* ForInStatement */:
- case 232 /* ForOfStatement */:
- case 229 /* WhileStatement */:
- case 228 /* DoStatement */:
- return !statement.label || isLabeledBy(node, statement.label.escapedText);
- default:
- // Don't cross function boundaries.
- // TODO: GH#20090
- return ts.isFunctionLike(node) && "quit";
- }
- });
- }
- function getModifierOccurrences(modifier, declaration) {
- return ts.mapDefined(getNodesToSearchForModifier(declaration, ts.modifierToFlag(modifier)), function (node) { return ts.findModifier(node, modifier); });
- }
- function getNodesToSearchForModifier(declaration, modifierFlag) {
- // Types of node whose children might have modifiers.
- var container = declaration.parent;
- switch (container.kind) {
- case 250 /* ModuleBlock */:
- case 290 /* SourceFile */:
- case 223 /* Block */:
- case 277 /* CaseClause */:
- case 278 /* DefaultClause */:
- // Container is either a class declaration or the declaration is a classDeclaration
- if (modifierFlag & 128 /* Abstract */ && ts.isClassDeclaration(declaration)) {
- return __spreadArrays(declaration.members, [declaration]);
- }
- else {
- return container.statements;
- }
- case 162 /* Constructor */:
- case 161 /* MethodDeclaration */:
- case 244 /* FunctionDeclaration */:
- return __spreadArrays(container.parameters, (ts.isClassLike(container.parent) ? container.parent.members : []));
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 246 /* InterfaceDeclaration */:
- case 173 /* TypeLiteral */:
- var nodes = container.members;
- // If we're an accessibility modifier, we're in an instance member and should search
- // the constructor's parameter list for instance members as well.
- if (modifierFlag & (28 /* AccessibilityModifier */ | 64 /* Readonly */)) {
- var constructor = ts.find(container.members, ts.isConstructorDeclaration);
- if (constructor) {
- return __spreadArrays(nodes, constructor.parameters);
- }
- }
- else if (modifierFlag & 128 /* Abstract */) {
- return __spreadArrays(nodes, [container]);
- }
- return nodes;
- default:
- ts.Debug.assertNever(container, "Invalid container kind.");
- }
- }
- function pushKeywordIf(keywordList, token) {
- var expected = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- expected[_i - 2] = arguments[_i];
- }
- if (token && ts.contains(expected, token.kind)) {
- keywordList.push(token);
- return true;
- }
- return false;
- }
- function getLoopBreakContinueOccurrences(loopNode) {
- var keywords = [];
- if (pushKeywordIf(keywords, loopNode.getFirstToken(), 93 /* ForKeyword */, 111 /* WhileKeyword */, 86 /* DoKeyword */)) {
- // If we succeeded and got a do-while loop, then start looking for a 'while' keyword.
- if (loopNode.kind === 228 /* DoStatement */) {
- var loopTokens = loopNode.getChildren();
- for (var i = loopTokens.length - 1; i >= 0; i--) {
- if (pushKeywordIf(keywords, loopTokens[i], 111 /* WhileKeyword */)) {
- break;
- }
- }
- }
- }
- ts.forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), function (statement) {
- if (ownsBreakOrContinueStatement(loopNode, statement)) {
- pushKeywordIf(keywords, statement.getFirstToken(), 77 /* BreakKeyword */, 82 /* ContinueKeyword */);
- }
- });
- return keywords;
- }
- function getBreakOrContinueStatementOccurrences(breakOrContinueStatement) {
- var owner = getBreakOrContinueOwner(breakOrContinueStatement);
- if (owner) {
- switch (owner.kind) {
- case 230 /* ForStatement */:
- case 231 /* ForInStatement */:
- case 232 /* ForOfStatement */:
- case 228 /* DoStatement */:
- case 229 /* WhileStatement */:
- return getLoopBreakContinueOccurrences(owner);
- case 237 /* SwitchStatement */:
- return getSwitchCaseDefaultOccurrences(owner);
- }
- }
- return undefined;
- }
- function getSwitchCaseDefaultOccurrences(switchStatement) {
- var keywords = [];
- pushKeywordIf(keywords, switchStatement.getFirstToken(), 103 /* SwitchKeyword */);
- // Go through each clause in the switch statement, collecting the 'case'/'default' keywords.
- ts.forEach(switchStatement.caseBlock.clauses, function (clause) {
- pushKeywordIf(keywords, clause.getFirstToken(), 78 /* CaseKeyword */, 84 /* DefaultKeyword */);
- ts.forEach(aggregateAllBreakAndContinueStatements(clause), function (statement) {
- if (ownsBreakOrContinueStatement(switchStatement, statement)) {
- pushKeywordIf(keywords, statement.getFirstToken(), 77 /* BreakKeyword */);
- }
- });
- });
- return keywords;
- }
- function getTryCatchFinallyOccurrences(tryStatement, sourceFile) {
- var keywords = [];
- pushKeywordIf(keywords, tryStatement.getFirstToken(), 107 /* TryKeyword */);
- if (tryStatement.catchClause) {
- pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 79 /* CatchKeyword */);
- }
- if (tryStatement.finallyBlock) {
- var finallyKeyword = ts.findChildOfKind(tryStatement, 92 /* FinallyKeyword */, sourceFile);
- pushKeywordIf(keywords, finallyKeyword, 92 /* FinallyKeyword */);
- }
- return keywords;
- }
- function getThrowOccurrences(throwStatement, sourceFile) {
- var owner = getThrowStatementOwner(throwStatement);
- if (!owner) {
- return undefined;
- }
- var keywords = [];
- ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) {
- keywords.push(ts.findChildOfKind(throwStatement, 105 /* ThrowKeyword */, sourceFile));
- });
- // If the "owner" is a function, then we equate 'return' and 'throw' statements in their
- // ability to "jump out" of the function, and include occurrences for both.
- if (ts.isFunctionBlock(owner)) {
- ts.forEachReturnStatement(owner, function (returnStatement) {
- keywords.push(ts.findChildOfKind(returnStatement, 101 /* ReturnKeyword */, sourceFile));
- });
- }
- return keywords;
- }
- function getReturnOccurrences(returnStatement, sourceFile) {
- var func = ts.getContainingFunction(returnStatement);
- if (!func) {
- return undefined;
- }
- var keywords = [];
- ts.forEachReturnStatement(ts.cast(func.body, ts.isBlock), function (returnStatement) {
- keywords.push(ts.findChildOfKind(returnStatement, 101 /* ReturnKeyword */, sourceFile));
- });
- // Include 'throw' statements that do not occur within a try block.
- ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) {
- keywords.push(ts.findChildOfKind(throwStatement, 105 /* ThrowKeyword */, sourceFile));
- });
- return keywords;
- }
- function getAsyncAndAwaitOccurrences(node) {
- var func = ts.getContainingFunction(node);
- if (!func) {
- return undefined;
- }
- var keywords = [];
- if (func.modifiers) {
- func.modifiers.forEach(function (modifier) {
- pushKeywordIf(keywords, modifier, 126 /* AsyncKeyword */);
- });
- }
- ts.forEachChild(func, function (child) {
- traverseWithoutCrossingFunction(child, function (node) {
- if (ts.isAwaitExpression(node)) {
- pushKeywordIf(keywords, node.getFirstToken(), 127 /* AwaitKeyword */);
- }
- });
- });
- return keywords;
- }
- function getYieldOccurrences(node) {
- var func = ts.getContainingFunction(node);
- if (!func) {
- return undefined;
- }
- var keywords = [];
- ts.forEachChild(func, function (child) {
- traverseWithoutCrossingFunction(child, function (node) {
- if (ts.isYieldExpression(node)) {
- pushKeywordIf(keywords, node.getFirstToken(), 121 /* YieldKeyword */);
- }
- });
- });
- return keywords;
- }
- // Do not cross function/class/interface/module/type boundaries.
- function traverseWithoutCrossingFunction(node, cb) {
- cb(node);
- if (!ts.isFunctionLike(node) && !ts.isClassLike(node) && !ts.isInterfaceDeclaration(node) && !ts.isModuleDeclaration(node) && !ts.isTypeAliasDeclaration(node) && !ts.isTypeNode(node)) {
- ts.forEachChild(node, function (child) { return traverseWithoutCrossingFunction(child, cb); });
- }
- }
- function getIfElseOccurrences(ifStatement, sourceFile) {
- var keywords = getIfElseKeywords(ifStatement, sourceFile);
- var result = [];
- // We'd like to highlight else/ifs together if they are only separated by whitespace
- // (i.e. the keywords are separated by no comments, no newlines).
- for (var i = 0; i < keywords.length; i++) {
- if (keywords[i].kind === 87 /* ElseKeyword */ && i < keywords.length - 1) {
- var elseKeyword = keywords[i];
- var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword.
- var shouldCombineElseAndIf = true;
- // Avoid recalculating getStart() by iterating backwards.
- for (var j = ifKeyword.getStart(sourceFile) - 1; j >= elseKeyword.end; j--) {
- if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) {
- shouldCombineElseAndIf = false;
- break;
- }
- }
- if (shouldCombineElseAndIf) {
- result.push({
- fileName: sourceFile.fileName,
- textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end),
- kind: "reference" /* reference */
- });
- i++; // skip the next keyword
- continue;
- }
- }
- // Ordinary case: just highlight the keyword.
- result.push(getHighlightSpanForNode(keywords[i], sourceFile));
- }
- return result;
- }
- function getIfElseKeywords(ifStatement, sourceFile) {
- var keywords = [];
- // Traverse upwards through all parent if-statements linked by their else-branches.
- while (ts.isIfStatement(ifStatement.parent) && ifStatement.parent.elseStatement === ifStatement) {
- ifStatement = ifStatement.parent;
- }
- // Now traverse back down through the else branches, aggregating if/else keywords of if-statements.
- while (true) {
- var children = ifStatement.getChildren(sourceFile);
- pushKeywordIf(keywords, children[0], 95 /* IfKeyword */);
- // Generally the 'else' keyword is second-to-last, so we traverse backwards.
- for (var i = children.length - 1; i >= 0; i--) {
- if (pushKeywordIf(keywords, children[i], 87 /* ElseKeyword */)) {
- break;
- }
- }
- if (!ifStatement.elseStatement || !ts.isIfStatement(ifStatement.elseStatement)) {
- break;
- }
- ifStatement = ifStatement.elseStatement;
- }
- return keywords;
- }
- /**
- * Whether or not a 'node' is preceded by a label of the given string.
- * Note: 'node' cannot be a SourceFile.
- */
- function isLabeledBy(node, labelName) {
- return !!ts.findAncestor(node.parent, function (owner) { return !ts.isLabeledStatement(owner) ? "quit" : owner.label.escapedText === labelName; });
- }
- })(DocumentHighlights = ts.DocumentHighlights || (ts.DocumentHighlights = {}));
-})(ts || (ts = {}));
-var ts;
-(function (ts) {
- function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) {
- return createDocumentRegistryInternal(useCaseSensitiveFileNames, currentDirectory);
- }
- ts.createDocumentRegistry = createDocumentRegistry;
- /*@internal*/
- function createDocumentRegistryInternal(useCaseSensitiveFileNames, currentDirectory, externalCache) {
- if (currentDirectory === void 0) { currentDirectory = ""; }
- // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
- // for those settings.
- var buckets = ts.createMap();
- var getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames);
- function reportStats() {
- var bucketInfoArray = ts.arrayFrom(buckets.keys()).filter(function (name) { return name && name.charAt(0) === "_"; }).map(function (name) {
- var entries = buckets.get(name);
- var sourceFiles = [];
- entries.forEach(function (entry, name) {
- sourceFiles.push({
- name: name,
- refCount: entry.languageServiceRefCount
- });
- });
- sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; });
- return {
- bucket: name,
- sourceFiles: sourceFiles
- };
- });
- return JSON.stringify(bucketInfoArray, undefined, 2);
- }
- function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) {
- var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- var key = getKeyForCompilationSettings(compilationSettings);
- return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind);
- }
- function acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) {
- return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind);
- }
- function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) {
- var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- var key = getKeyForCompilationSettings(compilationSettings);
- return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind);
- }
- function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) {
- return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind);
- }
- function acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, acquiring, scriptKind) {
- var bucket = ts.getOrUpdate(buckets, key, ts.createMap);
- var entry = bucket.get(path);
- var scriptTarget = scriptKind === 6 /* JSON */ ? 100 /* JSON */ : compilationSettings.target || 1 /* ES5 */;
- if (!entry && externalCache) {
- var sourceFile = externalCache.getDocument(key, path);
- if (sourceFile) {
- ts.Debug.assert(acquiring);
- entry = {
- sourceFile: sourceFile,
- languageServiceRefCount: 0
- };
- bucket.set(path, entry);
- }
- }
- if (!entry) {
- // Have never seen this file with these settings. Create a new source file for it.
- var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, /*setNodeParents*/ false, scriptKind);
- if (externalCache) {
- externalCache.setDocument(key, path, sourceFile);
- }
- entry = {
- sourceFile: sourceFile,
- languageServiceRefCount: 1,
- };
- bucket.set(path, entry);
- }
- else {
- // We have an entry for this file. However, it may be for a different version of
- // the script snapshot. If so, update it appropriately. Otherwise, we can just
- // return it as is.
- if (entry.sourceFile.version !== version) {
- entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot)); // TODO: GH#18217
- if (externalCache) {
- externalCache.setDocument(key, path, entry.sourceFile);
- }
- }
- // If we're acquiring, then this is the first time this LS is asking for this document.
- // Increase our ref count so we know there's another LS using the document. If we're
- // not acquiring, then that means the LS is 'updating' the file instead, and that means
- // it has already acquired the document previously. As such, we do not need to increase
- // the ref count.
- if (acquiring) {
- entry.languageServiceRefCount++;
- }
- }
- ts.Debug.assert(entry.languageServiceRefCount !== 0);
- return entry.sourceFile;
- }
- function releaseDocument(fileName, compilationSettings) {
- var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- var key = getKeyForCompilationSettings(compilationSettings);
- return releaseDocumentWithKey(path, key);
- }
- function releaseDocumentWithKey(path, key) {
- var bucket = ts.Debug.checkDefined(buckets.get(key));
- var entry = bucket.get(path);
- entry.languageServiceRefCount--;
- ts.Debug.assert(entry.languageServiceRefCount >= 0);
- if (entry.languageServiceRefCount === 0) {
- bucket.delete(path);
- }
- }
- function getLanguageServiceRefCounts(path) {
- return ts.arrayFrom(buckets.entries(), function (_a) {
- var key = _a[0], bucket = _a[1];
- var entry = bucket.get(path);
- return [key, entry && entry.languageServiceRefCount];
- });
- }
- return {
- acquireDocument: acquireDocument,
- acquireDocumentWithKey: acquireDocumentWithKey,
- updateDocument: updateDocument,
- updateDocumentWithKey: updateDocumentWithKey,
- releaseDocument: releaseDocument,
- releaseDocumentWithKey: releaseDocumentWithKey,
- getLanguageServiceRefCounts: getLanguageServiceRefCounts,
- reportStats: reportStats,
- getKeyForCompilationSettings: getKeyForCompilationSettings
- };
- }
- ts.createDocumentRegistryInternal = createDocumentRegistryInternal;
- function getKeyForCompilationSettings(settings) {
- return ts.sourceFileAffectingCompilerOptions.map(function (option) { return ts.getCompilerOptionValue(settings, option); }).join("|");
- }
-})(ts || (ts = {}));
-/* Code for finding imports of an exported symbol. Used only by FindAllReferences. */
-/* @internal */
-var ts;
-(function (ts) {
- var FindAllReferences;
- (function (FindAllReferences) {
- /** Creates the imports map and returns an ImportTracker that uses it. Call this lazily to avoid calling `getDirectImportsMap` unnecessarily. */
- function createImportTracker(sourceFiles, sourceFilesSet, checker, cancellationToken) {
- var allDirectImports = getDirectImportsMap(sourceFiles, checker, cancellationToken);
- return function (exportSymbol, exportInfo, isForRename) {
- var _a = getImportersForExport(sourceFiles, sourceFilesSet, allDirectImports, exportInfo, checker, cancellationToken), directImports = _a.directImports, indirectUsers = _a.indirectUsers;
- return __assign({ indirectUsers: indirectUsers }, getSearchesFromDirectImports(directImports, exportSymbol, exportInfo.exportKind, checker, isForRename));
- };
- }
- FindAllReferences.createImportTracker = createImportTracker;
- var ExportKind;
- (function (ExportKind) {
- ExportKind[ExportKind["Named"] = 0] = "Named";
- ExportKind[ExportKind["Default"] = 1] = "Default";
- ExportKind[ExportKind["ExportEquals"] = 2] = "ExportEquals";
- })(ExportKind = FindAllReferences.ExportKind || (FindAllReferences.ExportKind = {}));
- var ImportExport;
- (function (ImportExport) {
- ImportExport[ImportExport["Import"] = 0] = "Import";
- ImportExport[ImportExport["Export"] = 1] = "Export";
- })(ImportExport = FindAllReferences.ImportExport || (FindAllReferences.ImportExport = {}));
- /** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */
- function getImportersForExport(sourceFiles, sourceFilesSet, allDirectImports, _a, checker, cancellationToken) {
- var exportingModuleSymbol = _a.exportingModuleSymbol, exportKind = _a.exportKind;
- var markSeenDirectImport = ts.nodeSeenTracker();
- var markSeenIndirectUser = ts.nodeSeenTracker();
- var directImports = [];
- var isAvailableThroughGlobal = !!exportingModuleSymbol.globalExports;
- var indirectUserDeclarations = isAvailableThroughGlobal ? undefined : [];
- handleDirectImports(exportingModuleSymbol);
- return { directImports: directImports, indirectUsers: getIndirectUsers() };
- function getIndirectUsers() {
- if (isAvailableThroughGlobal) {
- // It has `export as namespace`, so anything could potentially use it.
- return sourceFiles;
- }
- // Module augmentations may use this module's exports without importing it.
- for (var _i = 0, _a = exportingModuleSymbol.declarations; _i < _a.length; _i++) {
- var decl = _a[_i];
- if (ts.isExternalModuleAugmentation(decl) && sourceFilesSet.has(decl.getSourceFile().fileName)) {
- addIndirectUser(decl);
- }
- }
- // This may return duplicates (if there are multiple module declarations in a single source file, all importing the same thing as a namespace), but `State.markSearchedSymbol` will handle that.
- return indirectUserDeclarations.map(ts.getSourceFileOfNode);
- }
- function handleDirectImports(exportingModuleSymbol) {
- var theseDirectImports = getDirectImports(exportingModuleSymbol);
- if (theseDirectImports) {
- for (var _i = 0, theseDirectImports_1 = theseDirectImports; _i < theseDirectImports_1.length; _i++) {
- var direct = theseDirectImports_1[_i];
- if (!markSeenDirectImport(direct)) {
- continue;
- }
- if (cancellationToken)
- cancellationToken.throwIfCancellationRequested();
- switch (direct.kind) {
- case 196 /* CallExpression */:
- if (!isAvailableThroughGlobal) {
- var parent = direct.parent;
- if (exportKind === 2 /* ExportEquals */ && parent.kind === 242 /* VariableDeclaration */) {
- var name = parent.name;
- if (name.kind === 75 /* Identifier */) {
- directImports.push(name);
- break;
- }
- }
- // Don't support re-exporting 'require()' calls, so just add a single indirect user.
- addIndirectUser(direct.getSourceFile());
- }
- break;
- case 75 /* Identifier */: // for 'const x = require("y");
- break; // TODO: GH#23879
- case 253 /* ImportEqualsDeclaration */:
- handleNamespaceImport(direct, direct.name, ts.hasModifier(direct, 1 /* Export */), /*alreadyAddedDirect*/ false);
- break;
- case 254 /* ImportDeclaration */:
- directImports.push(direct);
- var namedBindings = direct.importClause && direct.importClause.namedBindings;
- if (namedBindings && namedBindings.kind === 256 /* NamespaceImport */) {
- handleNamespaceImport(direct, namedBindings.name, /*isReExport*/ false, /*alreadyAddedDirect*/ true);
- }
- else if (!isAvailableThroughGlobal && ts.isDefaultImport(direct)) {
- addIndirectUser(getSourceFileLikeForImportDeclaration(direct)); // Add a check for indirect uses to handle synthetic default imports
- }
- break;
- case 260 /* ExportDeclaration */:
- if (!direct.exportClause) {
- // This is `export * from "foo"`, so imports of this module may import the export too.
- handleDirectImports(getContainingModuleSymbol(direct, checker));
- }
- else {
- // This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports.
- directImports.push(direct);
- }
- break;
- case 188 /* ImportType */:
- directImports.push(direct);
- break;
- default:
- ts.Debug.failBadSyntaxKind(direct, "Unexpected import kind.");
- }
- }
- }
- }
- function handleNamespaceImport(importDeclaration, name, isReExport, alreadyAddedDirect) {
- if (exportKind === 2 /* ExportEquals */) {
- // This is a direct import, not import-as-namespace.
- if (!alreadyAddedDirect)
- directImports.push(importDeclaration);
- }
- else if (!isAvailableThroughGlobal) {
- var sourceFileLike = getSourceFileLikeForImportDeclaration(importDeclaration);
- ts.Debug.assert(sourceFileLike.kind === 290 /* SourceFile */ || sourceFileLike.kind === 249 /* ModuleDeclaration */);
- if (isReExport || findNamespaceReExports(sourceFileLike, name, checker)) {
- addIndirectUsers(sourceFileLike);
- }
- else {
- addIndirectUser(sourceFileLike);
- }
- }
- }
- function addIndirectUser(sourceFileLike) {
- ts.Debug.assert(!isAvailableThroughGlobal);
- var isNew = markSeenIndirectUser(sourceFileLike);
- if (isNew) {
- indirectUserDeclarations.push(sourceFileLike); // TODO: GH#18217
- }
- return isNew;
- }
- /** Adds a module and all of its transitive dependencies as possible indirect users. */
- function addIndirectUsers(sourceFileLike) {
- if (!addIndirectUser(sourceFileLike)) {
- return;
- }
- var moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol);
- ts.Debug.assert(!!(moduleSymbol.flags & 1536 /* Module */));
- var directImports = getDirectImports(moduleSymbol);
- if (directImports) {
- for (var _i = 0, directImports_1 = directImports; _i < directImports_1.length; _i++) {
- var directImport = directImports_1[_i];
- if (!ts.isImportTypeNode(directImport)) {
- addIndirectUsers(getSourceFileLikeForImportDeclaration(directImport));
- }
- }
- }
- }
- function getDirectImports(moduleSymbol) {
- return allDirectImports.get(ts.getSymbolId(moduleSymbol).toString());
- }
- }
- /**
- * Given the set of direct imports of a module, we need to find which ones import the particular exported symbol.
- * The returned `importSearches` will result in the entire source file being searched.
- * But re-exports will be placed in 'singleReferences' since they cannot be locally referenced.
- */
- function getSearchesFromDirectImports(directImports, exportSymbol, exportKind, checker, isForRename) {
- var importSearches = [];
- var singleReferences = [];
- function addSearch(location, symbol) {
- importSearches.push([location, symbol]);
- }
- if (directImports) {
- for (var _i = 0, directImports_2 = directImports; _i < directImports_2.length; _i++) {
- var decl = directImports_2[_i];
- handleImport(decl);
- }
- }
- return { importSearches: importSearches, singleReferences: singleReferences };
- function handleImport(decl) {
- if (decl.kind === 253 /* ImportEqualsDeclaration */) {
- if (isExternalModuleImportEquals(decl)) {
- handleNamespaceImportLike(decl.name);
- }
- return;
- }
- if (decl.kind === 75 /* Identifier */) {
- handleNamespaceImportLike(decl);
- return;
- }
- if (decl.kind === 188 /* ImportType */) {
- if (decl.qualifier) {
- var firstIdentifier = ts.getFirstIdentifier(decl.qualifier);
- if (firstIdentifier.escapedText === ts.symbolName(exportSymbol)) {
- singleReferences.push(firstIdentifier);
- }
- }
- else if (exportKind === 2 /* ExportEquals */) {
- singleReferences.push(decl.argument.literal);
- }
- return;
- }
- // Ignore if there's a grammar error
- if (decl.moduleSpecifier.kind !== 10 /* StringLiteral */) {
- return;
- }
- if (decl.kind === 260 /* ExportDeclaration */) {
- if (decl.exportClause && ts.isNamedExports(decl.exportClause)) {
- searchForNamedImport(decl.exportClause);
- }
- return;
- }
- var _a = decl.importClause || { name: undefined, namedBindings: undefined }, name = _a.name, namedBindings = _a.namedBindings;
- if (namedBindings) {
- switch (namedBindings.kind) {
- case 256 /* NamespaceImport */:
- handleNamespaceImportLike(namedBindings.name);
- break;
- case 257 /* NamedImports */:
- // 'default' might be accessed as a named import `{ default as foo }`.
- if (exportKind === 0 /* Named */ || exportKind === 1 /* Default */) {
- searchForNamedImport(namedBindings);
- }
- break;
- default:
- ts.Debug.assertNever(namedBindings);
- }
- }
- // `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals.
- // If a default import has the same name as the default export, allow to rename it.
- // Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that.
- if (name && (exportKind === 1 /* Default */ || exportKind === 2 /* ExportEquals */) && (!isForRename || name.escapedText === ts.symbolEscapedNameNoDefault(exportSymbol))) {
- var defaultImportAlias = checker.getSymbolAtLocation(name);
- addSearch(name, defaultImportAlias);
- }
- }
- /**
- * `import x = require("./x")` or `import * as x from "./x"`.
- * An `export =` may be imported by this syntax, so it may be a direct import.
- * If it's not a direct import, it will be in `indirectUsers`, so we don't have to do anything here.
- */
- function handleNamespaceImportLike(importName) {
- // Don't rename an import that already has a different name than the export.
- if (exportKind === 2 /* ExportEquals */ && (!isForRename || isNameMatch(importName.escapedText))) {
- addSearch(importName, checker.getSymbolAtLocation(importName));
- }
- }
- function searchForNamedImport(namedBindings) {
- if (!namedBindings) {
- return;
- }
- for (var _i = 0, _a = namedBindings.elements; _i < _a.length; _i++) {
- var element = _a[_i];
- var name = element.name, propertyName = element.propertyName;
- if (!isNameMatch((propertyName || name).escapedText)) {
- continue;
- }
- if (propertyName) {
- // This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference.
- singleReferences.push(propertyName);
- // If renaming `{ foo as bar }`, don't touch `bar`, just `foo`.
- // But do rename `foo` in ` { default as foo }` if that's the original export name.
- if (!isForRename || name.escapedText === exportSymbol.escapedName) {
- // Search locally for `bar`.
- addSearch(name, checker.getSymbolAtLocation(name));
- }
- }
- else {
- var localSymbol = element.kind === 263 /* ExportSpecifier */ && element.propertyName
- ? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol.
- : checker.getSymbolAtLocation(name);
- addSearch(name, localSymbol);
- }
- }
- }
- function isNameMatch(name) {
- // Use name of "default" even in `export =` case because we may have allowSyntheticDefaultImports
- return name === exportSymbol.escapedName || exportKind !== 0 /* Named */ && name === "default" /* Default */;
- }
- }
- /** Returns 'true' is the namespace 'name' is re-exported from this module, and 'false' if it is only used locally. */
- function findNamespaceReExports(sourceFileLike, name, checker) {
- var namespaceImportSymbol = checker.getSymbolAtLocation(name);
- return !!forEachPossibleImportOrExportStatement(sourceFileLike, function (statement) {
- if (!ts.isExportDeclaration(statement))
- return;
- var exportClause = statement.exportClause, moduleSpecifier = statement.moduleSpecifier;
- return !moduleSpecifier && exportClause && ts.isNamedExports(exportClause) &&
- exportClause.elements.some(function (element) { return checker.getExportSpecifierLocalTargetSymbol(element) === namespaceImportSymbol; });
- });
- }
- function findModuleReferences(program, sourceFiles, searchModuleSymbol) {
- var refs = [];
- var checker = program.getTypeChecker();
- for (var _i = 0, sourceFiles_1 = sourceFiles; _i < sourceFiles_1.length; _i++) {
- var referencingFile = sourceFiles_1[_i];
- var searchSourceFile = searchModuleSymbol.valueDeclaration;
- if (searchSourceFile.kind === 290 /* SourceFile */) {
- for (var _a = 0, _b = referencingFile.referencedFiles; _a < _b.length; _a++) {
- var ref = _b[_a];
- if (program.getSourceFileFromReference(referencingFile, ref) === searchSourceFile) {
- refs.push({ kind: "reference", referencingFile: referencingFile, ref: ref });
- }
- }
- for (var _c = 0, _d = referencingFile.typeReferenceDirectives; _c < _d.length; _c++) {
- var ref = _d[_c];
- var referenced = program.getResolvedTypeReferenceDirectives().get(ref.fileName);
- if (referenced !== undefined && referenced.resolvedFileName === searchSourceFile.fileName) {
- refs.push({ kind: "reference", referencingFile: referencingFile, ref: ref });
- }
- }
- }
- forEachImport(referencingFile, function (_importDecl, moduleSpecifier) {
- var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier);
- if (moduleSymbol === searchModuleSymbol) {
- refs.push({ kind: "import", literal: moduleSpecifier });
- }
- });
- }
- return refs;
- }
- FindAllReferences.findModuleReferences = findModuleReferences;
- /** Returns a map from a module symbol Id to all import statements that directly reference the module. */
- function getDirectImportsMap(sourceFiles, checker, cancellationToken) {
- var map = ts.createMap();
- for (var _i = 0, sourceFiles_2 = sourceFiles; _i < sourceFiles_2.length; _i++) {
- var sourceFile = sourceFiles_2[_i];
- if (cancellationToken)
- cancellationToken.throwIfCancellationRequested();
- forEachImport(sourceFile, function (importDecl, moduleSpecifier) {
- var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier);
- if (moduleSymbol) {
- var id = ts.getSymbolId(moduleSymbol).toString();
- var imports = map.get(id);
- if (!imports) {
- map.set(id, imports = []);
- }
- imports.push(importDecl);
- }
- });
- }
- return map;
- }
- /** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */
- function forEachPossibleImportOrExportStatement(sourceFileLike, action) {
- return ts.forEach(sourceFileLike.kind === 290 /* SourceFile */ ? sourceFileLike.statements : sourceFileLike.body.statements, function (statement) {
- return action(statement) || (isAmbientModuleDeclaration(statement) && ts.forEach(statement.body && statement.body.statements, action));
- });
- }
- /** Calls `action` for each import, re-export, or require() in a file. */
- function forEachImport(sourceFile, action) {
- if (sourceFile.externalModuleIndicator || sourceFile.imports !== undefined) {
- for (var _i = 0, _a = sourceFile.imports; _i < _a.length; _i++) {
- var i = _a[_i];
- action(ts.importFromModuleSpecifier(i), i);
- }
- }
- else {
- forEachPossibleImportOrExportStatement(sourceFile, function (statement) {
- switch (statement.kind) {
- case 260 /* ExportDeclaration */:
- case 254 /* ImportDeclaration */: {
- var decl = statement;
- if (decl.moduleSpecifier && ts.isStringLiteral(decl.moduleSpecifier)) {
- action(decl, decl.moduleSpecifier);
- }
- break;
- }
- case 253 /* ImportEqualsDeclaration */: {
- var decl = statement;
- if (isExternalModuleImportEquals(decl)) {
- action(decl, decl.moduleReference.expression);
- }
- break;
- }
- }
- });
- }
- }
- /**
- * Given a local reference, we might notice that it's an import/export and recursively search for references of that.
- * If at an import, look locally for the symbol it imports.
- * If at an export, look for all imports of it.
- * This doesn't handle export specifiers; that is done in `getReferencesAtExportSpecifier`.
- * @param comingFromExport If we are doing a search for all exports, don't bother looking backwards for the imported symbol, since that's the reason we're here.
- */
- function getImportOrExportSymbol(node, symbol, checker, comingFromExport) {
- return comingFromExport ? getExport() : getExport() || getImport();
- function getExport() {
- var parent = node.parent;
- var grandParent = parent.parent;
- if (symbol.exportSymbol) {
- if (parent.kind === 194 /* PropertyAccessExpression */) {
- // When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use.
- // So check that we are at the declaration.
- return symbol.declarations.some(function (d) { return d === parent; }) && ts.isBinaryExpression(grandParent)
- ? getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ false)
- : undefined;
- }
- else {
- return exportInfo(symbol.exportSymbol, getExportKindForDeclaration(parent));
- }
- }
- else {
- var exportNode = getExportNode(parent, node);
- if (exportNode && ts.hasModifier(exportNode, 1 /* Export */)) {
- if (ts.isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) {
- // We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement.
- if (comingFromExport) {
- return undefined;
- }
- var lhsSymbol = checker.getSymbolAtLocation(exportNode.name);
- return { kind: 0 /* Import */, symbol: lhsSymbol };
- }
- else {
- return exportInfo(symbol, getExportKindForDeclaration(exportNode));
- }
- }
- // If we are in `export = a;` or `export default a;`, `parent` is the export assignment.
- else if (ts.isExportAssignment(parent)) {
- return getExportAssignmentExport(parent);
- }
- // If we are in `export = class A {};` (or `export = class A {};`) at `A`, `parent.parent` is the export assignment.
- else if (ts.isExportAssignment(grandParent)) {
- return getExportAssignmentExport(grandParent);
- }
- // Similar for `module.exports =` and `exports.A =`.
- else if (ts.isBinaryExpression(parent)) {
- return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true);
- }
- else if (ts.isBinaryExpression(grandParent)) {
- return getSpecialPropertyExport(grandParent, /*useLhsSymbol*/ true);
- }
- else if (ts.isJSDocTypedefTag(parent)) {
- return exportInfo(symbol, 0 /* Named */);
- }
- }
- function getExportAssignmentExport(ex) {
- // Get the symbol for the `export =` node; its parent is the module it's the export of.
- var exportingModuleSymbol = ts.Debug.checkDefined(ex.symbol.parent, "Expected export symbol to have a parent");
- var exportKind = ex.isExportEquals ? 2 /* ExportEquals */ : 1 /* Default */;
- return { kind: 1 /* Export */, symbol: symbol, exportInfo: { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } };
- }
- function getSpecialPropertyExport(node, useLhsSymbol) {
- var kind;
- switch (ts.getAssignmentDeclarationKind(node)) {
- case 1 /* ExportsProperty */:
- kind = 0 /* Named */;
- break;
- case 2 /* ModuleExports */:
- kind = 2 /* ExportEquals */;
- break;
- default:
- return undefined;
- }
- var sym = useLhsSymbol ? checker.getSymbolAtLocation(ts.getNameOfAccessExpression(ts.cast(node.left, ts.isAccessExpression))) : symbol;
- return sym && exportInfo(sym, kind);
- }
- }
- function getImport() {
- var isImport = isNodeImport(node);
- if (!isImport)
- return undefined;
- // A symbol being imported is always an alias. So get what that aliases to find the local symbol.
- var importedSymbol = checker.getImmediateAliasedSymbol(symbol);
- if (!importedSymbol)
- return undefined;
- // Search on the local symbol in the exporting module, not the exported symbol.
- importedSymbol = skipExportSpecifierSymbol(importedSymbol, checker);
- // Similarly, skip past the symbol for 'export ='
- if (importedSymbol.escapedName === "export=") {
- importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker);
- }
- // If the import has a different name than the export, do not continue searching.
- // If `importedName` is undefined, do continue searching as the export is anonymous.
- // (All imports returned from this function will be ignored anyway if we are in rename and this is a not a named export.)
- var importedName = ts.symbolEscapedNameNoDefault(importedSymbol);
- if (importedName === undefined || importedName === "default" /* Default */ || importedName === symbol.escapedName) {
- return { kind: 0 /* Import */, symbol: importedSymbol };
- }
- }
- function exportInfo(symbol, kind) {
- var exportInfo = getExportInfo(symbol, kind, checker);
- return exportInfo && { kind: 1 /* Export */, symbol: symbol, exportInfo: exportInfo };
- }
- // Not meant for use with export specifiers or export assignment.
- function getExportKindForDeclaration(node) {
- return ts.hasModifier(node, 512 /* Default */) ? 1 /* Default */ : 0 /* Named */;
- }
- }
- FindAllReferences.getImportOrExportSymbol = getImportOrExportSymbol;
- function getExportEqualsLocalSymbol(importedSymbol, checker) {
- if (importedSymbol.flags & 2097152 /* Alias */) {
- return ts.Debug.checkDefined(checker.getImmediateAliasedSymbol(importedSymbol));
- }
- var decl = importedSymbol.valueDeclaration;
- if (ts.isExportAssignment(decl)) { // `export = class {}`
- return ts.Debug.checkDefined(decl.expression.symbol);
- }
- else if (ts.isBinaryExpression(decl)) { // `module.exports = class {}`
- return ts.Debug.checkDefined(decl.right.symbol);
- }
- else if (ts.isSourceFile(decl)) { // json module
- return ts.Debug.checkDefined(decl.symbol);
- }
- return ts.Debug.fail();
- }
- // If a reference is a class expression, the exported node would be its parent.
- // If a reference is a variable declaration, the exported node would be the variable statement.
- function getExportNode(parent, node) {
- var declaration = ts.isVariableDeclaration(parent) ? parent : ts.isBindingElement(parent) ? ts.walkUpBindingElementsAndPatterns(parent) : undefined;
- if (declaration) {
- return parent.name !== node ? undefined :
- ts.isCatchClause(declaration.parent) ? undefined : ts.isVariableStatement(declaration.parent.parent) ? declaration.parent.parent : undefined;
- }
- else {
- return parent;
- }
- }
- function isNodeImport(node) {
- var parent = node.parent;
- switch (parent.kind) {
- case 253 /* ImportEqualsDeclaration */:
- return parent.name === node && isExternalModuleImportEquals(parent);
- case 258 /* ImportSpecifier */:
- // For a rename import `{ foo as bar }`, don't search for the imported symbol. Just find local uses of `bar`.
- return !parent.propertyName;
- case 255 /* ImportClause */:
- case 256 /* NamespaceImport */:
- ts.Debug.assert(parent.name === node);
- return true;
- default:
- return false;
- }
- }
- function getExportInfo(exportSymbol, exportKind, checker) {
- var moduleSymbol = exportSymbol.parent;
- if (!moduleSymbol)
- return undefined; // This can happen if an `export` is not at the top-level (which is a compile error).
- var exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); // Need to get merged symbol in case there's an augmentation.
- // `export` may appear in a namespace. In that case, just rely on global search.
- return ts.isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } : undefined;
- }
- FindAllReferences.getExportInfo = getExportInfo;
- /** If at an export specifier, go to the symbol it refers to. */
- function skipExportSpecifierSymbol(symbol, checker) {
- // For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does.
- if (symbol.declarations) {
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (ts.isExportSpecifier(declaration) && !declaration.propertyName && !declaration.parent.parent.moduleSpecifier) {
- return checker.getExportSpecifierLocalTargetSymbol(declaration);
- }
- }
- }
- return symbol;
- }
- function getContainingModuleSymbol(importer, checker) {
- return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol);
- }
- function getSourceFileLikeForImportDeclaration(node) {
- if (node.kind === 196 /* CallExpression */) {
- return node.getSourceFile();
- }
- var parent = node.parent;
- if (parent.kind === 290 /* SourceFile */) {
- return parent;
- }
- ts.Debug.assert(parent.kind === 250 /* ModuleBlock */);
- return ts.cast(parent.parent, isAmbientModuleDeclaration);
- }
- function isAmbientModuleDeclaration(node) {
- return node.kind === 249 /* ModuleDeclaration */ && node.name.kind === 10 /* StringLiteral */;
- }
- function isExternalModuleImportEquals(eq) {
- return eq.moduleReference.kind === 265 /* ExternalModuleReference */ && eq.moduleReference.expression.kind === 10 /* StringLiteral */;
- }
- })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var FindAllReferences;
- (function (FindAllReferences) {
- var DefinitionKind;
- (function (DefinitionKind) {
- DefinitionKind[DefinitionKind["Symbol"] = 0] = "Symbol";
- DefinitionKind[DefinitionKind["Label"] = 1] = "Label";
- DefinitionKind[DefinitionKind["Keyword"] = 2] = "Keyword";
- DefinitionKind[DefinitionKind["This"] = 3] = "This";
- DefinitionKind[DefinitionKind["String"] = 4] = "String";
- })(DefinitionKind = FindAllReferences.DefinitionKind || (FindAllReferences.DefinitionKind = {}));
- var EntryKind;
- (function (EntryKind) {
- EntryKind[EntryKind["Span"] = 0] = "Span";
- EntryKind[EntryKind["Node"] = 1] = "Node";
- EntryKind[EntryKind["StringLiteral"] = 2] = "StringLiteral";
- EntryKind[EntryKind["SearchedLocalFoundProperty"] = 3] = "SearchedLocalFoundProperty";
- EntryKind[EntryKind["SearchedPropertyFoundLocal"] = 4] = "SearchedPropertyFoundLocal";
- })(EntryKind = FindAllReferences.EntryKind || (FindAllReferences.EntryKind = {}));
- function nodeEntry(node, kind) {
- if (kind === void 0) { kind = 1 /* Node */; }
- return {
- kind: kind,
- node: node.name || node,
- context: getContextNodeForNodeEntry(node)
- };
- }
- FindAllReferences.nodeEntry = nodeEntry;
- function isContextWithStartAndEndNode(node) {
- return node && node.kind === undefined;
- }
- FindAllReferences.isContextWithStartAndEndNode = isContextWithStartAndEndNode;
- function getContextNodeForNodeEntry(node) {
- if (ts.isDeclaration(node)) {
- return getContextNode(node);
- }
- if (!node.parent)
- return undefined;
- if (!ts.isDeclaration(node.parent) && !ts.isExportAssignment(node.parent)) {
- // Special property assignment in javascript
- if (ts.isInJSFile(node)) {
- var binaryExpression = ts.isBinaryExpression(node.parent) ?
- node.parent :
- ts.isAccessExpression(node.parent) &&
- ts.isBinaryExpression(node.parent.parent) &&
- node.parent.parent.left === node.parent ?
- node.parent.parent :
- undefined;
- if (binaryExpression && ts.getAssignmentDeclarationKind(binaryExpression) !== 0 /* None */) {
- return getContextNode(binaryExpression);
- }
- }
- // Jsx Tags
- if (ts.isJsxOpeningElement(node.parent) || ts.isJsxClosingElement(node.parent)) {
- return node.parent.parent;
- }
- else if (ts.isJsxSelfClosingElement(node.parent) ||
- ts.isLabeledStatement(node.parent) ||
- ts.isBreakOrContinueStatement(node.parent)) {
- return node.parent;
- }
- else if (ts.isStringLiteralLike(node)) {
- var validImport = ts.tryGetImportFromModuleSpecifier(node);
- if (validImport) {
- var declOrStatement = ts.findAncestor(validImport, function (node) {
- return ts.isDeclaration(node) ||
- ts.isStatement(node) ||
- ts.isJSDocTag(node);
- });
- return ts.isDeclaration(declOrStatement) ?
- getContextNode(declOrStatement) :
- declOrStatement;
- }
- }
- // Handle computed property name
- var propertyName = ts.findAncestor(node, ts.isComputedPropertyName);
- return propertyName ?
- getContextNode(propertyName.parent) :
- undefined;
- }
- if (node.parent.name === node || // node is name of declaration, use parent
- ts.isConstructorDeclaration(node.parent) ||
- ts.isExportAssignment(node.parent) ||
- // Property name of the import export specifier or binding pattern, use parent
- ((ts.isImportOrExportSpecifier(node.parent) || ts.isBindingElement(node.parent))
- && node.parent.propertyName === node) ||
- // Is default export
- (node.kind === 84 /* DefaultKeyword */ && ts.hasModifier(node.parent, 513 /* ExportDefault */))) {
- return getContextNode(node.parent);
- }
- return undefined;
- }
- function getContextNode(node) {
- if (!node)
- return undefined;
- switch (node.kind) {
- case 242 /* VariableDeclaration */:
- return !ts.isVariableDeclarationList(node.parent) || node.parent.declarations.length !== 1 ?
- node :
- ts.isVariableStatement(node.parent.parent) ?
- node.parent.parent :
- ts.isForInOrOfStatement(node.parent.parent) ?
- getContextNode(node.parent.parent) :
- node.parent;
- case 191 /* BindingElement */:
- return getContextNode(node.parent.parent);
- case 258 /* ImportSpecifier */:
- return node.parent.parent.parent;
- case 263 /* ExportSpecifier */:
- case 256 /* NamespaceImport */:
- return node.parent.parent;
- case 255 /* ImportClause */:
- return node.parent;
- case 209 /* BinaryExpression */:
- return ts.isExpressionStatement(node.parent) ?
- node.parent :
- node;
- case 232 /* ForOfStatement */:
- case 231 /* ForInStatement */:
- return {
- start: node.initializer,
- end: node.expression
- };
- case 281 /* PropertyAssignment */:
- case 282 /* ShorthandPropertyAssignment */:
- return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent) ?
- getContextNode(ts.findAncestor(node.parent, function (node) {
- return ts.isBinaryExpression(node) || ts.isForInOrOfStatement(node);
- })) :
- node;
- default:
- return node;
- }
- }
- FindAllReferences.getContextNode = getContextNode;
- function toContextSpan(textSpan, sourceFile, context) {
- if (!context)
- return undefined;
- var contextSpan = isContextWithStartAndEndNode(context) ?
- getTextSpan(context.start, sourceFile, context.end) :
- getTextSpan(context, sourceFile);
- return contextSpan.start !== textSpan.start || contextSpan.length !== textSpan.length ?
- { contextSpan: contextSpan } :
- undefined;
- }
- FindAllReferences.toContextSpan = toContextSpan;
- var FindReferencesUse;
- (function (FindReferencesUse) {
- /**
- * When searching for references to a symbol, the location will not be adjusted (this is the default behavior when not specified).
- */
- FindReferencesUse[FindReferencesUse["Other"] = 0] = "Other";
- /**
- * When searching for references to a symbol, the location will be adjusted if the cursor was on a keyword.
- */
- FindReferencesUse[FindReferencesUse["References"] = 1] = "References";
- /**
- * When searching for references to a symbol, the location will be adjusted if the cursor was on a keyword.
- * Unlike `References`, the location will only be adjusted keyword belonged to a declaration with a valid name.
- * If set, we will find fewer references -- if it is referenced by several different names, we still only find references for the original name.
- */
- FindReferencesUse[FindReferencesUse["Rename"] = 2] = "Rename";
- })(FindReferencesUse = FindAllReferences.FindReferencesUse || (FindAllReferences.FindReferencesUse = {}));
- function findReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position) {
- var node = ts.getTouchingPropertyName(sourceFile, position);
- var referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, { use: 1 /* References */ });
- var checker = program.getTypeChecker();
- return !referencedSymbols || !referencedSymbols.length ? undefined : ts.mapDefined(referencedSymbols, function (_a) {
- var definition = _a.definition, references = _a.references;
- // Only include referenced symbols that have a valid definition.
- return definition && {
- definition: checker.runWithCancellationToken(cancellationToken, function (checker) { return definitionToReferencedSymbolDefinitionInfo(definition, checker, node); }),
- references: references.map(toReferenceEntry)
- };
- });
- }
- FindAllReferences.findReferencedSymbols = findReferencedSymbols;
- function getImplementationsAtPosition(program, cancellationToken, sourceFiles, sourceFile, position) {
- var node = ts.getTouchingPropertyName(sourceFile, position);
- var referenceEntries;
- var entries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position);
- if (node.parent.kind === 194 /* PropertyAccessExpression */
- || node.parent.kind === 191 /* BindingElement */
- || node.parent.kind === 195 /* ElementAccessExpression */
- || node.kind === 102 /* SuperKeyword */) {
- referenceEntries = entries && __spreadArrays(entries);
- }
- else {
- var queue = entries && __spreadArrays(entries);
- var seenNodes = ts.createMap();
- while (queue && queue.length) {
- var entry = queue.shift();
- if (!ts.addToSeen(seenNodes, ts.getNodeId(entry.node))) {
- continue;
- }
- referenceEntries = ts.append(referenceEntries, entry);
- var entries_1 = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, entry.node, entry.node.pos);
- if (entries_1) {
- queue.push.apply(queue, entries_1);
- }
- }
- }
- var checker = program.getTypeChecker();
- return ts.map(referenceEntries, function (entry) { return toImplementationLocation(entry, checker); });
- }
- FindAllReferences.getImplementationsAtPosition = getImplementationsAtPosition;
- function getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position) {
- if (node.kind === 290 /* SourceFile */) {
- return undefined;
- }
- var checker = program.getTypeChecker();
- // If invoked directly on a shorthand property assignment, then return
- // the declaration of the symbol being assigned (not the symbol being assigned to).
- if (node.parent.kind === 282 /* ShorthandPropertyAssignment */) {
- var result_1 = [];
- Core.getReferenceEntriesForShorthandPropertyAssignment(node, checker, function (node) { return result_1.push(nodeEntry(node)); });
- return result_1;
- }
- else if (node.kind === 102 /* SuperKeyword */ || ts.isSuperProperty(node.parent)) {
- // References to and accesses on the super keyword only have one possible implementation, so no
- // need to "Find all References"
- var symbol = checker.getSymbolAtLocation(node);
- return symbol.valueDeclaration && [nodeEntry(symbol.valueDeclaration)];
- }
- else {
- // Perform "Find all References" and retrieve only those that are implementations
- return getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, { implementations: true, use: 1 /* References */ });
- }
- }
- function findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, convertEntry) {
- return ts.map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), function (entry) { return convertEntry(entry, node, program.getTypeChecker()); });
- }
- FindAllReferences.findReferenceOrRenameEntries = findReferenceOrRenameEntries;
- function getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet) {
- if (options === void 0) { options = {}; }
- if (sourceFilesSet === void 0) { sourceFilesSet = ts.arrayToSet(sourceFiles, function (f) { return f.fileName; }); }
- return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet));
- }
- FindAllReferences.getReferenceEntriesForNode = getReferenceEntriesForNode;
- function flattenEntries(referenceSymbols) {
- return referenceSymbols && ts.flatMap(referenceSymbols, function (r) { return r.references; });
- }
- function definitionToReferencedSymbolDefinitionInfo(def, checker, originalNode) {
- var info = (function () {
- switch (def.type) {
- case 0 /* Symbol */: {
- var symbol = def.symbol;
- var _a = getDefinitionKindAndDisplayParts(symbol, checker, originalNode), displayParts_1 = _a.displayParts, kind_1 = _a.kind;
- var name_1 = displayParts_1.map(function (p) { return p.text; }).join("");
- var declaration = symbol.declarations ? ts.first(symbol.declarations) : undefined;
- return {
- node: declaration ?
- ts.getNameOfDeclaration(declaration) || declaration :
- originalNode,
- name: name_1,
- kind: kind_1,
- displayParts: displayParts_1,
- context: getContextNode(declaration)
- };
- }
- case 1 /* Label */: {
- var node_1 = def.node;
- return { node: node_1, name: node_1.text, kind: "label" /* label */, displayParts: [ts.displayPart(node_1.text, ts.SymbolDisplayPartKind.text)] };
- }
- case 2 /* Keyword */: {
- var node_2 = def.node;
- var name_2 = ts.tokenToString(node_2.kind);
- return { node: node_2, name: name_2, kind: "keyword" /* keyword */, displayParts: [{ text: name_2, kind: "keyword" /* keyword */ }] };
- }
- case 3 /* This */: {
- var node_3 = def.node;
- var symbol = checker.getSymbolAtLocation(node_3);
- var displayParts_2 = symbol && ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, node_3.getSourceFile(), ts.getContainerNode(node_3), node_3).displayParts || [ts.textPart("this")];
- return { node: node_3, name: "this", kind: "var" /* variableElement */, displayParts: displayParts_2 };
- }
- case 4 /* String */: {
- var node_4 = def.node;
- return { node: node_4, name: node_4.text, kind: "var" /* variableElement */, displayParts: [ts.displayPart(ts.getTextOfNode(node_4), ts.SymbolDisplayPartKind.stringLiteral)] };
- }
- default:
- return ts.Debug.assertNever(def);
- }
- })();
- var node = info.node, name = info.name, kind = info.kind, displayParts = info.displayParts, context = info.context;
- var sourceFile = node.getSourceFile();
- var textSpan = getTextSpan(ts.isComputedPropertyName(node) ? node.expression : node, sourceFile);
- return __assign({ containerKind: "" /* unknown */, containerName: "", fileName: sourceFile.fileName, kind: kind,
- name: name,
- textSpan: textSpan,
- displayParts: displayParts }, toContextSpan(textSpan, sourceFile, context));
- }
- function getDefinitionKindAndDisplayParts(symbol, checker, node) {
- var meaning = Core.getIntersectingMeaningFromDeclarations(node, symbol);
- var enclosingDeclaration = symbol.declarations && ts.firstOrUndefined(symbol.declarations) || node;
- var _a = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning), displayParts = _a.displayParts, symbolKind = _a.symbolKind;
- return { displayParts: displayParts, kind: symbolKind };
- }
- function toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixText) {
- return __assign(__assign({}, entryToDocumentSpan(entry)), (providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker)));
- }
- FindAllReferences.toRenameLocation = toRenameLocation;
- function toReferenceEntry(entry) {
- var documentSpan = entryToDocumentSpan(entry);
- if (entry.kind === 0 /* Span */) {
- return __assign(__assign({}, documentSpan), { isWriteAccess: false, isDefinition: false });
- }
- var kind = entry.kind, node = entry.node;
- return __assign(__assign({}, documentSpan), { isWriteAccess: isWriteAccessForReference(node), isDefinition: isDefinitionForReference(node), isInString: kind === 2 /* StringLiteral */ ? true : undefined });
- }
- FindAllReferences.toReferenceEntry = toReferenceEntry;
- function entryToDocumentSpan(entry) {
- if (entry.kind === 0 /* Span */) {
- return { textSpan: entry.textSpan, fileName: entry.fileName };
- }
- else {
- var sourceFile = entry.node.getSourceFile();
- var textSpan = getTextSpan(entry.node, sourceFile);
- return __assign({ textSpan: textSpan, fileName: sourceFile.fileName }, toContextSpan(textSpan, sourceFile, entry.context));
- }
- }
- function getPrefixAndSuffixText(entry, originalNode, checker) {
- if (entry.kind !== 0 /* Span */ && ts.isIdentifier(originalNode)) {
- var node = entry.node, kind = entry.kind;
- var name = originalNode.text;
- var isShorthandAssignment = ts.isShorthandPropertyAssignment(node.parent);
- if (isShorthandAssignment || ts.isObjectBindingElementWithoutPropertyName(node.parent) && node.parent.name === node) {
- var prefixColon = { prefixText: name + ": " };
- var suffixColon = { suffixText: ": " + name };
- return kind === 3 /* SearchedLocalFoundProperty */ ? prefixColon
- : kind === 4 /* SearchedPropertyFoundLocal */ ? suffixColon
- // In `const o = { x }; o.x`, symbolAtLocation at `x` in `{ x }` is the property symbol.
- // For a binding element `const { x } = o;`, symbolAtLocation at `x` is the property symbol.
- : isShorthandAssignment ? suffixColon : prefixColon;
- }
- else if (ts.isImportSpecifier(entry.node.parent) && !entry.node.parent.propertyName) {
- // If the original symbol was using this alias, just rename the alias.
- var originalSymbol = ts.isExportSpecifier(originalNode.parent) ? checker.getExportSpecifierLocalTargetSymbol(originalNode.parent) : checker.getSymbolAtLocation(originalNode);
- return ts.contains(originalSymbol.declarations, entry.node.parent) ? { prefixText: name + " as " } : ts.emptyOptions;
- }
- else if (ts.isExportSpecifier(entry.node.parent) && !entry.node.parent.propertyName) {
- // If the symbol for the node is same as declared node symbol use prefix text
- return originalNode === entry.node || checker.getSymbolAtLocation(originalNode) === checker.getSymbolAtLocation(entry.node) ?
- { prefixText: name + " as " } :
- { suffixText: " as " + name };
- }
- }
- return ts.emptyOptions;
- }
- function toImplementationLocation(entry, checker) {
- var documentSpan = entryToDocumentSpan(entry);
- if (entry.kind !== 0 /* Span */) {
- var node = entry.node;
- return __assign(__assign({}, documentSpan), implementationKindDisplayParts(node, checker));
- }
- else {
- return __assign(__assign({}, documentSpan), { kind: "" /* unknown */, displayParts: [] });
- }
- }
- function implementationKindDisplayParts(node, checker) {
- var symbol = checker.getSymbolAtLocation(ts.isDeclaration(node) && node.name ? node.name : node);
- if (symbol) {
- return getDefinitionKindAndDisplayParts(symbol, checker, node);
- }
- else if (node.kind === 193 /* ObjectLiteralExpression */) {
- return {
- kind: "interface" /* interfaceElement */,
- displayParts: [ts.punctuationPart(20 /* OpenParenToken */), ts.textPart("object literal"), ts.punctuationPart(21 /* CloseParenToken */)]
- };
- }
- else if (node.kind === 214 /* ClassExpression */) {
- return {
- kind: "local class" /* localClassElement */,
- displayParts: [ts.punctuationPart(20 /* OpenParenToken */), ts.textPart("anonymous local class"), ts.punctuationPart(21 /* CloseParenToken */)]
- };
- }
- else {
- return { kind: ts.getNodeKind(node), displayParts: [] };
- }
- }
- function toHighlightSpan(entry) {
- var documentSpan = entryToDocumentSpan(entry);
- if (entry.kind === 0 /* Span */) {
- return {
- fileName: documentSpan.fileName,
- span: {
- textSpan: documentSpan.textSpan,
- kind: "reference" /* reference */
- }
- };
- }
- var writeAccess = isWriteAccessForReference(entry.node);
- var span = __assign({ textSpan: documentSpan.textSpan, kind: writeAccess ? "writtenReference" /* writtenReference */ : "reference" /* reference */, isInString: entry.kind === 2 /* StringLiteral */ ? true : undefined }, documentSpan.contextSpan && { contextSpan: documentSpan.contextSpan });
- return { fileName: documentSpan.fileName, span: span };
- }
- FindAllReferences.toHighlightSpan = toHighlightSpan;
- function getTextSpan(node, sourceFile, endNode) {
- var start = node.getStart(sourceFile);
- var end = (endNode || node).getEnd();
- if (ts.isStringLiteralLike(node)) {
- ts.Debug.assert(endNode === undefined);
- start += 1;
- end -= 1;
- }
- return ts.createTextSpanFromBounds(start, end);
- }
- function getTextSpanOfEntry(entry) {
- return entry.kind === 0 /* Span */ ? entry.textSpan :
- getTextSpan(entry.node, entry.node.getSourceFile());
- }
- FindAllReferences.getTextSpanOfEntry = getTextSpanOfEntry;
- /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
- function isWriteAccessForReference(node) {
- var decl = ts.getDeclarationFromName(node);
- return !!decl && declarationIsWriteAccess(decl) || node.kind === 84 /* DefaultKeyword */ || ts.isWriteAccess(node);
- }
- function isDefinitionForReference(node) {
- return node.kind === 84 /* DefaultKeyword */
- || !!ts.getDeclarationFromName(node)
- || ts.isLiteralComputedPropertyDeclarationName(node)
- || (node.kind === 129 /* ConstructorKeyword */ && ts.isConstructorDeclaration(node.parent));
- }
- /**
- * True if 'decl' provides a value, as in `function f() {}`;
- * false if 'decl' is just a location for a future write, as in 'let x;'
- */
- function declarationIsWriteAccess(decl) {
- // Consider anything in an ambient declaration to be a write access since it may be coming from JS.
- if (!!(decl.flags & 8388608 /* Ambient */))
- return true;
- switch (decl.kind) {
- case 209 /* BinaryExpression */:
- case 191 /* BindingElement */:
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 84 /* DefaultKeyword */:
- case 248 /* EnumDeclaration */:
- case 284 /* EnumMember */:
- case 263 /* ExportSpecifier */:
- case 255 /* ImportClause */: // default import
- case 253 /* ImportEqualsDeclaration */:
- case 258 /* ImportSpecifier */:
- case 246 /* InterfaceDeclaration */:
- case 315 /* JSDocCallbackTag */:
- case 322 /* JSDocTypedefTag */:
- case 273 /* JsxAttribute */:
- case 249 /* ModuleDeclaration */:
- case 252 /* NamespaceExportDeclaration */:
- case 256 /* NamespaceImport */:
- case 262 /* NamespaceExport */:
- case 156 /* Parameter */:
- case 282 /* ShorthandPropertyAssignment */:
- case 247 /* TypeAliasDeclaration */:
- case 155 /* TypeParameter */:
- return true;
- case 281 /* PropertyAssignment */:
- // In `({ x: y } = 0);`, `x` is not a write access. (Won't call this function for `y`.)
- return !ts.isArrayLiteralOrObjectLiteralDestructuringPattern(decl.parent);
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 162 /* Constructor */:
- case 161 /* MethodDeclaration */:
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- return !!decl.body;
- case 242 /* VariableDeclaration */:
- case 159 /* PropertyDeclaration */:
- return !!decl.initializer || ts.isCatchClause(decl.parent);
- case 160 /* MethodSignature */:
- case 158 /* PropertySignature */:
- case 323 /* JSDocPropertyTag */:
- case 317 /* JSDocParameterTag */:
- return false;
- default:
- return ts.Debug.failBadSyntaxKind(decl);
- }
- }
- /** Encapsulates the core find-all-references algorithm. */
- var Core;
- (function (Core) {
- /** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */
- function getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet) {
- if (options === void 0) { options = {}; }
- if (sourceFilesSet === void 0) { sourceFilesSet = ts.arrayToSet(sourceFiles, function (f) { return f.fileName; }); }
- if (options.use === 1 /* References */) {
- node = ts.getAdjustedReferenceLocation(node);
- }
- else if (options.use === 2 /* Rename */) {
- node = ts.getAdjustedRenameLocation(node);
- }
- if (ts.isSourceFile(node)) {
- var reference = ts.GoToDefinition.getReferenceAtPosition(node, position, program);
- var moduleSymbol = reference && program.getTypeChecker().getMergedSymbol(reference.file.symbol);
- return moduleSymbol && getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet);
- }
- if (!options.implementations) {
- var special = getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken);
- if (special) {
- return special;
- }
- }
- var checker = program.getTypeChecker();
- var symbol = checker.getSymbolAtLocation(node);
- // Could not find a symbol e.g. unknown identifier
- if (!symbol) {
- // String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial.
- return !options.implementations && ts.isStringLiteral(node) ? getReferencesForStringLiteral(node, sourceFiles, cancellationToken) : undefined;
- }
- if (symbol.escapedName === "export=" /* ExportEquals */) {
- return getReferencedSymbolsForModule(program, symbol.parent, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet);
- }
- var moduleReferences = getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol, program, sourceFiles, cancellationToken, options, sourceFilesSet);
- if (moduleReferences && !(symbol.flags & 33554432 /* Transient */)) {
- return moduleReferences;
- }
- var aliasedSymbol = getMergedAliasedSymbolOfNamespaceExportDeclaration(node, symbol, checker);
- var moduleReferencesOfExportTarget = aliasedSymbol &&
- getReferencedSymbolsForModuleIfDeclaredBySourceFile(aliasedSymbol, program, sourceFiles, cancellationToken, options, sourceFilesSet);
- var references = getReferencedSymbolsForSymbol(symbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options);
- return mergeReferences(program, moduleReferences, references, moduleReferencesOfExportTarget);
- }
- Core.getReferencedSymbolsForNode = getReferencedSymbolsForNode;
- function getMergedAliasedSymbolOfNamespaceExportDeclaration(node, symbol, checker) {
- if (node.parent && ts.isNamespaceExportDeclaration(node.parent)) {
- var aliasedSymbol = checker.getAliasedSymbol(symbol);
- var targetSymbol = checker.getMergedSymbol(aliasedSymbol);
- if (aliasedSymbol !== targetSymbol) {
- return targetSymbol;
- }
- }
- return undefined;
- }
- function getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol, program, sourceFiles, cancellationToken, options, sourceFilesSet) {
- var moduleSourceFile = (symbol.flags & 1536 /* Module */) && symbol.declarations && ts.find(symbol.declarations, ts.isSourceFile);
- if (!moduleSourceFile)
- return undefined;
- var exportEquals = symbol.exports.get("export=" /* ExportEquals */);
- // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them.
- var moduleReferences = getReferencedSymbolsForModule(program, symbol, !!exportEquals, sourceFiles, sourceFilesSet);
- if (!exportEquals || !sourceFilesSet.has(moduleSourceFile.fileName))
- return moduleReferences;
- // Continue to get references to 'export ='.
- var checker = program.getTypeChecker();
- symbol = ts.skipAlias(exportEquals, checker);
- return mergeReferences(program, moduleReferences, getReferencedSymbolsForSymbol(symbol, /*node*/ undefined, sourceFiles, sourceFilesSet, checker, cancellationToken, options));
- }
- /**
- * Merges the references by sorting them (by file index in sourceFiles and their location in it) that point to same definition symbol
- */
- function mergeReferences(program) {
- var referencesToMerge = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- referencesToMerge[_i - 1] = arguments[_i];
- }
- var result;
- for (var _a = 0, referencesToMerge_1 = referencesToMerge; _a < referencesToMerge_1.length; _a++) {
- var references = referencesToMerge_1[_a];
- if (!references || !references.length)
- continue;
- if (!result) {
- result = references;
- continue;
- }
- var _loop_3 = function (entry) {
- if (!entry.definition || entry.definition.type !== 0 /* Symbol */) {
- result.push(entry);
- return "continue";
- }
- var symbol = entry.definition.symbol;
- var refIndex = ts.findIndex(result, function (ref) { return !!ref.definition &&
- ref.definition.type === 0 /* Symbol */ &&
- ref.definition.symbol === symbol; });
- if (refIndex === -1) {
- result.push(entry);
- return "continue";
- }
- var reference = result[refIndex];
- result[refIndex] = {
- definition: reference.definition,
- references: reference.references.concat(entry.references).sort(function (entry1, entry2) {
- var entry1File = getSourceFileIndexOfEntry(program, entry1);
- var entry2File = getSourceFileIndexOfEntry(program, entry2);
- if (entry1File !== entry2File) {
- return ts.compareValues(entry1File, entry2File);
- }
- var entry1Span = getTextSpanOfEntry(entry1);
- var entry2Span = getTextSpanOfEntry(entry2);
- return entry1Span.start !== entry2Span.start ?
- ts.compareValues(entry1Span.start, entry2Span.start) :
- ts.compareValues(entry1Span.length, entry2Span.length);
- })
- };
- };
- for (var _b = 0, references_1 = references; _b < references_1.length; _b++) {
- var entry = references_1[_b];
- _loop_3(entry);
- }
- }
- return result;
- }
- function getSourceFileIndexOfEntry(program, entry) {
- var sourceFile = entry.kind === 0 /* Span */ ?
- program.getSourceFile(entry.fileName) :
- entry.node.getSourceFile();
- return program.getSourceFiles().indexOf(sourceFile);
- }
- function getReferencedSymbolsForModule(program, symbol, excludeImportTypeOfExportEquals, sourceFiles, sourceFilesSet) {
- ts.Debug.assert(!!symbol.valueDeclaration);
- var references = ts.mapDefined(FindAllReferences.findModuleReferences(program, sourceFiles, symbol), function (reference) {
- if (reference.kind === "import") {
- var parent = reference.literal.parent;
- if (ts.isLiteralTypeNode(parent)) {
- var importType = ts.cast(parent.parent, ts.isImportTypeNode);
- if (excludeImportTypeOfExportEquals && !importType.qualifier) {
- return undefined;
- }
- }
- // import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway.
- return nodeEntry(reference.literal);
- }
- else {
- return {
- kind: 0 /* Span */,
- fileName: reference.referencingFile.fileName,
- textSpan: ts.createTextSpanFromRange(reference.ref),
- };
- }
- });
- if (symbol.declarations) {
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var decl = _a[_i];
- switch (decl.kind) {
- case 290 /* SourceFile */:
- // Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.)
- break;
- case 249 /* ModuleDeclaration */:
- if (sourceFilesSet.has(decl.getSourceFile().fileName)) {
- references.push(nodeEntry(decl.name));
- }
- break;
- default:
- // This may be merged with something.
- ts.Debug.assert(!!(symbol.flags & 33554432 /* Transient */), "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration.");
- }
- }
- }
- var exported = symbol.exports.get("export=" /* ExportEquals */);
- if (exported) {
- for (var _b = 0, _c = exported.declarations; _b < _c.length; _b++) {
- var decl = _c[_b];
- var sourceFile = decl.getSourceFile();
- if (sourceFilesSet.has(sourceFile.fileName)) {
- // At `module.exports = ...`, reference node is `module`
- var node = ts.isBinaryExpression(decl) && ts.isPropertyAccessExpression(decl.left) ? decl.left.expression :
- ts.isExportAssignment(decl) ? ts.Debug.checkDefined(ts.findChildOfKind(decl, 89 /* ExportKeyword */, sourceFile)) :
- ts.getNameOfDeclaration(decl) || decl;
- references.push(nodeEntry(node));
- }
- }
- }
- return references.length ? [{ definition: { type: 0 /* Symbol */, symbol: symbol }, references: references }] : ts.emptyArray;
- }
- /** As in a `readonly prop: any` or `constructor(readonly prop: any)`, not a `readonly any[]`. */
- function isReadonlyTypeOperator(node) {
- return node.kind === 138 /* ReadonlyKeyword */
- && ts.isTypeOperatorNode(node.parent)
- && node.parent.operator === 138 /* ReadonlyKeyword */;
- }
- /** getReferencedSymbols for special node kinds. */
- function getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken) {
- if (ts.isTypeKeyword(node.kind)) {
- // A void expression (i.e., `void foo()`) is not special, but the `void` type is.
- if (node.kind === 110 /* VoidKeyword */ && ts.isVoidExpression(node.parent)) {
- return undefined;
- }
- // A modifier readonly (like on a property declaration) is not special;
- // a readonly type keyword (like `readonly string[]`) is.
- if (node.kind === 138 /* ReadonlyKeyword */ && !isReadonlyTypeOperator(node)) {
- return undefined;
- }
- // Likewise, when we *are* looking for a special keyword, make sure we
- // *don’t* include readonly member modifiers.
- return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken, node.kind === 138 /* ReadonlyKeyword */ ? isReadonlyTypeOperator : undefined);
- }
- // Labels
- if (ts.isJumpStatementTarget(node)) {
- var labelDefinition = ts.getTargetLabel(node.parent, node.text);
- // if we have a label definition, look within its statement for references, if not, then
- // the label is undefined and we have no results..
- return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition);
- }
- else if (ts.isLabelOfLabeledStatement(node)) {
- // it is a label definition and not a target, search within the parent labeledStatement
- return getLabelReferencesInNode(node.parent, node);
- }
- if (ts.isThis(node)) {
- return getReferencesForThisKeyword(node, sourceFiles, cancellationToken);
- }
- if (node.kind === 102 /* SuperKeyword */) {
- return getReferencesForSuperKeyword(node);
- }
- return undefined;
- }
- /** Core find-all-references algorithm for a normal symbol. */
- function getReferencedSymbolsForSymbol(originalSymbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options) {
- var symbol = node && skipPastExportOrImportSpecifierOrUnion(originalSymbol, node, checker, /*useLocalSymbolForExportSpecifier*/ !isForRenameWithPrefixAndSuffixText(options)) || originalSymbol;
- // Compute the meaning from the location and the symbol it references
- var searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : 7 /* All */;
- var result = [];
- var state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : 0 /* None */, checker, cancellationToken, searchMeaning, options, result);
- var exportSpecifier = !isForRenameWithPrefixAndSuffixText(options) ? undefined : ts.find(symbol.declarations, ts.isExportSpecifier);
- if (exportSpecifier) {
- // When renaming at an export specifier, rename the export and not the thing being exported.
- getReferencesAtExportSpecifier(exportSpecifier.name, symbol, exportSpecifier, state.createSearch(node, originalSymbol, /*comingFrom*/ undefined), state, /*addReferencesHere*/ true, /*alwaysGetReferences*/ true);
- }
- else if (node && node.kind === 84 /* DefaultKeyword */) {
- addReference(node, symbol, state);
- searchForImportsOfExport(node, symbol, { exportingModuleSymbol: ts.Debug.checkDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: 1 /* Default */ }, state);
- }
- else {
- var search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, options.use === 2 /* Rename */, !!options.providePrefixAndSuffixTextForRename, !!options.implementations) : [symbol] });
- getReferencesInContainerOrFiles(symbol, state, search);
- }
- return result;
- }
- function getReferencesInContainerOrFiles(symbol, state, search) {
- // Try to get the smallest valid scope that we can limit our search to;
- // otherwise we'll need to search globally (i.e. include each file).
- var scope = getSymbolScope(symbol);
- if (scope) {
- getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(ts.isSourceFile(scope) && !ts.contains(state.sourceFiles, scope)));
- }
- else {
- // Global search
- for (var _i = 0, _a = state.sourceFiles; _i < _a.length; _i++) {
- var sourceFile = _a[_i];
- state.cancellationToken.throwIfCancellationRequested();
- searchForName(sourceFile, search, state);
- }
- }
- }
- function getSpecialSearchKind(node) {
- switch (node.kind) {
- case 129 /* ConstructorKeyword */:
- return 1 /* Constructor */;
- case 75 /* Identifier */:
- if (ts.isClassLike(node.parent)) {
- ts.Debug.assert(node.parent.name === node);
- return 2 /* Class */;
- }
- // falls through
- default:
- return 0 /* None */;
- }
- }
- /** Handle a few special cases relating to export/import specifiers. */
- function skipPastExportOrImportSpecifierOrUnion(symbol, node, checker, useLocalSymbolForExportSpecifier) {
- var parent = node.parent;
- if (ts.isExportSpecifier(parent) && useLocalSymbolForExportSpecifier) {
- return getLocalSymbolForExportSpecifier(node, symbol, parent, checker);
- }
- // If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references.
- return ts.firstDefined(symbol.declarations, function (decl) {
- if (!decl.parent) {
- // Ignore UMD module and global merge
- if (symbol.flags & 33554432 /* Transient */)
- return undefined;
- // Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here.
- ts.Debug.fail("Unexpected symbol at " + ts.Debug.formatSyntaxKind(node.kind) + ": " + ts.Debug.formatSymbol(symbol));
- }
- return ts.isTypeLiteralNode(decl.parent) && ts.isUnionTypeNode(decl.parent.parent)
- ? checker.getPropertyOfType(checker.getTypeFromTypeNode(decl.parent.parent), symbol.name)
- : undefined;
- });
- }
- var SpecialSearchKind;
- (function (SpecialSearchKind) {
- SpecialSearchKind[SpecialSearchKind["None"] = 0] = "None";
- SpecialSearchKind[SpecialSearchKind["Constructor"] = 1] = "Constructor";
- SpecialSearchKind[SpecialSearchKind["Class"] = 2] = "Class";
- })(SpecialSearchKind || (SpecialSearchKind = {}));
- function getNonModuleSymbolOfMergedModuleSymbol(symbol) {
- if (!(symbol.flags & (1536 /* Module */ | 33554432 /* Transient */)))
- return undefined;
- var decl = symbol.declarations && ts.find(symbol.declarations, function (d) { return !ts.isSourceFile(d) && !ts.isModuleDeclaration(d); });
- return decl && decl.symbol;
- }
- /**
- * Holds all state needed for the finding references.
- * Unlike `Search`, there is only one `State`.
- */
- var State = /** @class */ (function () {
- function State(sourceFiles, sourceFilesSet, specialSearchKind, checker, cancellationToken, searchMeaning, options, result) {
- this.sourceFiles = sourceFiles;
- this.sourceFilesSet = sourceFilesSet;
- this.specialSearchKind = specialSearchKind;
- this.checker = checker;
- this.cancellationToken = cancellationToken;
- this.searchMeaning = searchMeaning;
- this.options = options;
- this.result = result;
- /** Cache for `explicitlyinheritsFrom`. */
- this.inheritsFromCache = ts.createMap();
- /**
- * Type nodes can contain multiple references to the same type. For example:
- * let x: Foo & (Foo & Bar) = ...
- * Because we are returning the implementation locations and not the identifier locations,
- * duplicate entries would be returned here as each of the type references is part of
- * the same implementation. For that reason, check before we add a new entry.
- */
- this.markSeenContainingTypeReference = ts.nodeSeenTracker();
- /**
- * It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once.
- * For example:
- * // b.ts
- * export { foo as bar } from "./a";
- * import { bar } from "./b";
- *
- * Normally at `foo as bar` we directly add `foo` and do not locally search for it (since it doesn't declare a local).
- * But another reference to it may appear in the same source file.
- * See `tests/cases/fourslash/transitiveExportImports3.ts`.
- */
- this.markSeenReExportRHS = ts.nodeSeenTracker();
- this.symbolIdToReferences = [];
- // Source file ID → symbol ID → Whether the symbol has been searched for in the source file.
- this.sourceFileToSeenSymbols = [];
- }
- State.prototype.includesSourceFile = function (sourceFile) {
- return this.sourceFilesSet.has(sourceFile.fileName);
- };
- /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
- State.prototype.getImportSearches = function (exportSymbol, exportInfo) {
- if (!this.importTracker)
- this.importTracker = FindAllReferences.createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken);
- return this.importTracker(exportSymbol, exportInfo, this.options.use === 2 /* Rename */);
- };
- /** @param allSearchSymbols set of additional symbols for use by `includes`. */
- State.prototype.createSearch = function (location, symbol, comingFrom, searchOptions) {
- if (searchOptions === void 0) { searchOptions = {}; }
- // Note: if this is an external module symbol, the name doesn't include quotes.
- // Note: getLocalSymbolForExportDefault handles `export default class C {}`, but not `export default C` or `export { C as default }`.
- // The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form
- // here appears to be intentional).
- var _a = searchOptions.text, text = _a === void 0 ? ts.stripQuotes(ts.symbolName(ts.getLocalSymbolForExportDefault(symbol) || getNonModuleSymbolOfMergedModuleSymbol(symbol) || symbol)) : _a, _b = searchOptions.allSearchSymbols, allSearchSymbols = _b === void 0 ? [symbol] : _b;
- var escapedText = ts.escapeLeadingUnderscores(text);
- var parents = this.options.implementations && location ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined;
- return { symbol: symbol, comingFrom: comingFrom, text: text, escapedText: escapedText, parents: parents, allSearchSymbols: allSearchSymbols, includes: function (sym) { return ts.contains(allSearchSymbols, sym); } };
- };
- /**
- * Callback to add references for a particular searched symbol.
- * This initializes a reference group, so only call this if you will add at least one reference.
- */
- State.prototype.referenceAdder = function (searchSymbol) {
- var symbolId = ts.getSymbolId(searchSymbol);
- var references = this.symbolIdToReferences[symbolId];
- if (!references) {
- references = this.symbolIdToReferences[symbolId] = [];
- this.result.push({ definition: { type: 0 /* Symbol */, symbol: searchSymbol }, references: references });
- }
- return function (node, kind) { return references.push(nodeEntry(node, kind)); };
- };
- /** Add a reference with no associated definition. */
- State.prototype.addStringOrCommentReference = function (fileName, textSpan) {
- this.result.push({
- definition: undefined,
- references: [{ kind: 0 /* Span */, fileName: fileName, textSpan: textSpan }]
- });
- };
- /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */
- State.prototype.markSearchedSymbols = function (sourceFile, symbols) {
- var sourceId = ts.getNodeId(sourceFile);
- var seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = ts.createMap());
- var anyNewSymbols = false;
- for (var _i = 0, symbols_3 = symbols; _i < symbols_3.length; _i++) {
- var sym = symbols_3[_i];
- anyNewSymbols = ts.addToSeen(seenSymbols, ts.getSymbolId(sym)) || anyNewSymbols;
- }
- return anyNewSymbols;
- };
- return State;
- }());
- /** Search for all imports of a given exported symbol using `State.getImportSearches`. */
- function searchForImportsOfExport(exportLocation, exportSymbol, exportInfo, state) {
- var _a = state.getImportSearches(exportSymbol, exportInfo), importSearches = _a.importSearches, singleReferences = _a.singleReferences, indirectUsers = _a.indirectUsers;
- // For `import { foo as bar }` just add the reference to `foo`, and don't otherwise search in the file.
- if (singleReferences.length) {
- var addRef = state.referenceAdder(exportSymbol);
- for (var _i = 0, singleReferences_1 = singleReferences; _i < singleReferences_1.length; _i++) {
- var singleRef = singleReferences_1[_i];
- if (shouldAddSingleReference(singleRef, state))
- addRef(singleRef);
- }
- }
- // For each import, find all references to that import in its source file.
- for (var _b = 0, importSearches_1 = importSearches; _b < importSearches_1.length; _b++) {
- var _c = importSearches_1[_b], importLocation = _c[0], importSymbol = _c[1];
- getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, 1 /* Export */), state);
- }
- if (indirectUsers.length) {
- var indirectSearch = void 0;
- switch (exportInfo.exportKind) {
- case 0 /* Named */:
- indirectSearch = state.createSearch(exportLocation, exportSymbol, 1 /* Export */);
- break;
- case 1 /* Default */:
- // Search for a property access to '.default'. This can't be renamed.
- indirectSearch = state.options.use === 2 /* Rename */ ? undefined : state.createSearch(exportLocation, exportSymbol, 1 /* Export */, { text: "default" });
- break;
- case 2 /* ExportEquals */:
- break;
- }
- if (indirectSearch) {
- for (var _d = 0, indirectUsers_1 = indirectUsers; _d < indirectUsers_1.length; _d++) {
- var indirectUser = indirectUsers_1[_d];
- searchForName(indirectUser, indirectSearch, state);
- }
- }
- }
- }
- function eachExportReference(sourceFiles, checker, cancellationToken, exportSymbol, exportingModuleSymbol, exportName, isDefaultExport, cb) {
- var importTracker = FindAllReferences.createImportTracker(sourceFiles, ts.arrayToSet(sourceFiles, function (f) { return f.fileName; }), checker, cancellationToken);
- var _a = importTracker(exportSymbol, { exportKind: isDefaultExport ? 1 /* Default */ : 0 /* Named */, exportingModuleSymbol: exportingModuleSymbol }, /*isForRename*/ false), importSearches = _a.importSearches, indirectUsers = _a.indirectUsers;
- for (var _i = 0, importSearches_2 = importSearches; _i < importSearches_2.length; _i++) {
- var importLocation = importSearches_2[_i][0];
- cb(importLocation);
- }
- for (var _b = 0, indirectUsers_2 = indirectUsers; _b < indirectUsers_2.length; _b++) {
- var indirectUser = indirectUsers_2[_b];
- for (var _c = 0, _d = getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName); _c < _d.length; _c++) {
- var node = _d[_c];
- // Import specifiers should be handled by importSearches
- if (ts.isIdentifier(node) && !ts.isImportOrExportSpecifier(node.parent) && checker.getSymbolAtLocation(node) === exportSymbol) {
- cb(node);
- }
- }
- }
- }
- Core.eachExportReference = eachExportReference;
- function shouldAddSingleReference(singleRef, state) {
- if (!hasMatchingMeaning(singleRef, state))
- return false;
- if (state.options.use !== 2 /* Rename */)
- return true;
- // Don't rename an import type `import("./module-name")` when renaming `name` in `export = name;`
- if (!ts.isIdentifier(singleRef))
- return false;
- // At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename.
- return !(ts.isImportOrExportSpecifier(singleRef.parent) && singleRef.escapedText === "default" /* Default */);
- }
- // Go to the symbol we imported from and find references for it.
- function searchForImportedSymbol(symbol, state) {
- if (!symbol.declarations)
- return;
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- var exportingFile = declaration.getSourceFile();
- // Need to search in the file even if it's not in the search-file set, because it might export the symbol.
- getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, 0 /* Import */), state, state.includesSourceFile(exportingFile));
- }
- }
- /** Search for all occurences of an identifier in a source file (and filter out the ones that match). */
- function searchForName(sourceFile, search, state) {
- if (ts.getNameTable(sourceFile).get(search.escapedText) !== undefined) {
- getReferencesInSourceFile(sourceFile, search, state);
- }
- }
- function getPropertySymbolOfDestructuringAssignment(location, checker) {
- return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent)
- ? checker.getPropertySymbolOfDestructuringAssignment(location)
- : undefined;
- }
- /**
- * Determines the smallest scope in which a symbol may have named references.
- * Note that not every construct has been accounted for. This function can
- * probably be improved.
- *
- * @returns undefined if the scope cannot be determined, implying that
- * a reference to a symbol can occur anywhere.
- */
- function getSymbolScope(symbol) {
- // If this is the symbol of a named function expression or named class expression,
- // then named references are limited to its own scope.
- var declarations = symbol.declarations, flags = symbol.flags, parent = symbol.parent, valueDeclaration = symbol.valueDeclaration;
- if (valueDeclaration && (valueDeclaration.kind === 201 /* FunctionExpression */ || valueDeclaration.kind === 214 /* ClassExpression */)) {
- return valueDeclaration;
- }
- if (!declarations) {
- return undefined;
- }
- // If this is private property or method, the scope is the containing class
- if (flags & (4 /* Property */ | 8192 /* Method */)) {
- var privateDeclaration = ts.find(declarations, function (d) { return ts.hasModifier(d, 8 /* Private */) || ts.isPrivateIdentifierPropertyDeclaration(d); });
- if (privateDeclaration) {
- return ts.getAncestor(privateDeclaration, 245 /* ClassDeclaration */);
- }
- // Else this is a public property and could be accessed from anywhere.
- return undefined;
- }
- // If symbol is of object binding pattern element without property name we would want to
- // look for property too and that could be anywhere
- if (declarations.some(ts.isObjectBindingElementWithoutPropertyName)) {
- return undefined;
- }
- /*
- If the symbol has a parent, it's globally visible unless:
- - It's a private property (handled above).
- - It's a type parameter.
- - The parent is an external module: then we should only search in the module (and recurse on the export later).
- - But if the parent has `export as namespace`, the symbol is globally visible through that namespace.
- */
- var exposedByParent = parent && !(symbol.flags & 262144 /* TypeParameter */);
- if (exposedByParent && !(ts.isExternalModuleSymbol(parent) && !parent.globalExports)) {
- return undefined;
- }
- var scope;
- for (var _i = 0, declarations_1 = declarations; _i < declarations_1.length; _i++) {
- var declaration = declarations_1[_i];
- var container = ts.getContainerNode(declaration);
- if (scope && scope !== container) {
- // Different declarations have different containers, bail out
- return undefined;
- }
- if (!container || container.kind === 290 /* SourceFile */ && !ts.isExternalOrCommonJsModule(container)) {
- // This is a global variable and not an external module, any declaration defined
- // within this scope is visible outside the file
- return undefined;
- }
- // The search scope is the container node
- scope = container;
- }
- // If symbol.parent, this means we are in an export of an external module. (Otherwise we would have returned `undefined` above.)
- // For an export of a module, we may be in a declaration file, and it may be accessed elsewhere. E.g.:
- // declare module "a" { export type T = number; }
- // declare module "b" { import { T } from "a"; export const x: T; }
- // So we must search the whole source file. (Because we will mark the source file as seen, we we won't return to it when searching for imports.)
- return exposedByParent ? scope.getSourceFile() : scope; // TODO: GH#18217
- }
- /** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */
- function isSymbolReferencedInFile(definition, checker, sourceFile, searchContainer) {
- if (searchContainer === void 0) { searchContainer = sourceFile; }
- return eachSymbolReferenceInFile(definition, checker, sourceFile, function () { return true; }, searchContainer) || false;
- }
- Core.isSymbolReferencedInFile = isSymbolReferencedInFile;
- function eachSymbolReferenceInFile(definition, checker, sourceFile, cb, searchContainer) {
- if (searchContainer === void 0) { searchContainer = sourceFile; }
- var symbol = ts.isParameterPropertyDeclaration(definition.parent, definition.parent.parent)
- ? ts.first(checker.getSymbolsOfParameterPropertyDeclaration(definition.parent, definition.text))
- : checker.getSymbolAtLocation(definition);
- if (!symbol)
- return undefined;
- for (var _i = 0, _a = getPossibleSymbolReferenceNodes(sourceFile, symbol.name, searchContainer); _i < _a.length; _i++) {
- var token = _a[_i];
- if (!ts.isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText)
- continue;
- var referenceSymbol = checker.getSymbolAtLocation(token); // See GH#19955 for why the type annotation is necessary
- if (referenceSymbol === symbol
- || checker.getShorthandAssignmentValueSymbol(token.parent) === symbol
- || ts.isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol) {
- var res = cb(token);
- if (res)
- return res;
- }
- }
- }
- Core.eachSymbolReferenceInFile = eachSymbolReferenceInFile;
- function eachSignatureCall(signature, sourceFiles, checker, cb) {
- if (!signature.name || !ts.isIdentifier(signature.name))
- return;
- var symbol = ts.Debug.checkDefined(checker.getSymbolAtLocation(signature.name));
- for (var _i = 0, sourceFiles_3 = sourceFiles; _i < sourceFiles_3.length; _i++) {
- var sourceFile = sourceFiles_3[_i];
- for (var _a = 0, _b = getPossibleSymbolReferenceNodes(sourceFile, symbol.name); _a < _b.length; _a++) {
- var name = _b[_a];
- if (!ts.isIdentifier(name) || name === signature.name || name.escapedText !== signature.name.escapedText)
- continue;
- var called = ts.climbPastPropertyAccess(name);
- var call = called.parent;
- if (!ts.isCallExpression(call) || call.expression !== called)
- continue;
- var referenceSymbol = checker.getSymbolAtLocation(name);
- if (referenceSymbol && checker.getRootSymbols(referenceSymbol).some(function (s) { return s === symbol; })) {
- cb(call);
- }
- }
- }
- }
- Core.eachSignatureCall = eachSignatureCall;
- function getPossibleSymbolReferenceNodes(sourceFile, symbolName, container) {
- if (container === void 0) { container = sourceFile; }
- return getPossibleSymbolReferencePositions(sourceFile, symbolName, container).map(function (pos) { return ts.getTouchingPropertyName(sourceFile, pos); });
- }
- function getPossibleSymbolReferencePositions(sourceFile, symbolName, container) {
- if (container === void 0) { container = sourceFile; }
- var positions = [];
- /// TODO: Cache symbol existence for files to save text search
- // Also, need to make this work for unicode escapes.
- // Be resilient in the face of a symbol with no name or zero length name
- if (!symbolName || !symbolName.length) {
- return positions;
- }
- var text = sourceFile.text;
- var sourceLength = text.length;
- var symbolNameLength = symbolName.length;
- var position = text.indexOf(symbolName, container.pos);
- while (position >= 0) {
- // If we are past the end, stop looking
- if (position > container.end)
- break;
- // We found a match. Make sure it's not part of a larger word (i.e. the char
- // before and after it have to be a non-identifier char).
- var endPosition = position + symbolNameLength;
- if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 99 /* Latest */)) &&
- (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 99 /* Latest */))) {
- // Found a real match. Keep searching.
- positions.push(position);
- }
- position = text.indexOf(symbolName, position + symbolNameLength + 1);
- }
- return positions;
- }
- function getLabelReferencesInNode(container, targetLabel) {
- var sourceFile = container.getSourceFile();
- var labelName = targetLabel.text;
- var references = ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, labelName, container), function (node) {
- // Only pick labels that are either the target label, or have a target that is the target label
- return node === targetLabel || (ts.isJumpStatementTarget(node) && ts.getTargetLabel(node, labelName) === targetLabel) ? nodeEntry(node) : undefined;
- });
- return [{ definition: { type: 1 /* Label */, node: targetLabel }, references: references }];
- }
- function isValidReferencePosition(node, searchSymbolName) {
- // Compare the length so we filter out strict superstrings of the symbol we are looking for
- switch (node.kind) {
- case 76 /* PrivateIdentifier */:
- case 75 /* Identifier */:
- return node.text.length === searchSymbolName.length;
- case 14 /* NoSubstitutionTemplateLiteral */:
- case 10 /* StringLiteral */: {
- var str = node;
- return (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || ts.isNameOfModuleDeclaration(node) || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node) || (ts.isCallExpression(node.parent) && ts.isBindableObjectDefinePropertyCall(node.parent) && node.parent.arguments[1] === node)) &&
- str.text.length === searchSymbolName.length;
- }
- case 8 /* NumericLiteral */:
- return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && node.text.length === searchSymbolName.length;
- case 84 /* DefaultKeyword */:
- return "default".length === searchSymbolName.length;
- default:
- return false;
- }
- }
- function getAllReferencesForKeyword(sourceFiles, keywordKind, cancellationToken, filter) {
- var references = ts.flatMap(sourceFiles, function (sourceFile) {
- cancellationToken.throwIfCancellationRequested();
- return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, ts.tokenToString(keywordKind), sourceFile), function (referenceLocation) {
- if (referenceLocation.kind === keywordKind && (!filter || filter(referenceLocation))) {
- return nodeEntry(referenceLocation);
- }
- });
- });
- return references.length ? [{ definition: { type: 2 /* Keyword */, node: references[0].node }, references: references }] : undefined;
- }
- function getReferencesInSourceFile(sourceFile, search, state, addReferencesHere) {
- if (addReferencesHere === void 0) { addReferencesHere = true; }
- state.cancellationToken.throwIfCancellationRequested();
- return getReferencesInContainer(sourceFile, sourceFile, search, state, addReferencesHere);
- }
- /**
- * Search within node "container" for references for a search value, where the search value is defined as a
- * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
- * searchLocation: a node where the search value
- */
- function getReferencesInContainer(container, sourceFile, search, state, addReferencesHere) {
- if (!state.markSearchedSymbols(sourceFile, search.allSearchSymbols)) {
- return;
- }
- for (var _i = 0, _a = getPossibleSymbolReferencePositions(sourceFile, search.text, container); _i < _a.length; _i++) {
- var position = _a[_i];
- getReferencesAtLocation(sourceFile, position, search, state, addReferencesHere);
- }
- }
- function hasMatchingMeaning(referenceLocation, state) {
- return !!(ts.getMeaningFromLocation(referenceLocation) & state.searchMeaning);
- }
- function getReferencesAtLocation(sourceFile, position, search, state, addReferencesHere) {
- var referenceLocation = ts.getTouchingPropertyName(sourceFile, position);
- if (!isValidReferencePosition(referenceLocation, search.text)) {
- // This wasn't the start of a token. Check to see if it might be a
- // match in a comment or string if that's what the caller is asking
- // for.
- if (!state.options.implementations && (state.options.findInStrings && ts.isInString(sourceFile, position) || state.options.findInComments && ts.isInNonReferenceComment(sourceFile, position))) {
- // In the case where we're looking inside comments/strings, we don't have
- // an actual definition. So just use 'undefined' here. Features like
- // 'Rename' won't care (as they ignore the definitions), and features like
- // 'FindReferences' will just filter out these results.
- state.addStringOrCommentReference(sourceFile.fileName, ts.createTextSpan(position, search.text.length));
- }
- return;
- }
- if (!hasMatchingMeaning(referenceLocation, state))
- return;
- var referenceSymbol = state.checker.getSymbolAtLocation(referenceLocation);
- if (!referenceSymbol) {
- return;
- }
- var parent = referenceLocation.parent;
- if (ts.isImportSpecifier(parent) && parent.propertyName === referenceLocation) {
- // This is added through `singleReferences` in ImportsResult. If we happen to see it again, don't add it again.
- return;
- }
- if (ts.isExportSpecifier(parent)) {
- ts.Debug.assert(referenceLocation.kind === 75 /* Identifier */);
- getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, parent, search, state, addReferencesHere);
- return;
- }
- var relatedSymbol = getRelatedSymbol(search, referenceSymbol, referenceLocation, state);
- if (!relatedSymbol) {
- getReferenceForShorthandProperty(referenceSymbol, search, state);
- return;
- }
- switch (state.specialSearchKind) {
- case 0 /* None */:
- if (addReferencesHere)
- addReference(referenceLocation, relatedSymbol, state);
- break;
- case 1 /* Constructor */:
- addConstructorReferences(referenceLocation, sourceFile, search, state);
- break;
- case 2 /* Class */:
- addClassStaticThisReferences(referenceLocation, search, state);
- break;
- default:
- ts.Debug.assertNever(state.specialSearchKind);
- }
- getImportOrExportReferences(referenceLocation, referenceSymbol, search, state);
- }
- function getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, search, state, addReferencesHere, alwaysGetReferences) {
- ts.Debug.assert(!alwaysGetReferences || !!state.options.providePrefixAndSuffixTextForRename, "If alwaysGetReferences is true, then prefix/suffix text must be enabled");
- var parent = exportSpecifier.parent, propertyName = exportSpecifier.propertyName, name = exportSpecifier.name;
- var exportDeclaration = parent.parent;
- var localSymbol = getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, state.checker);
- if (!alwaysGetReferences && !search.includes(localSymbol)) {
- return;
- }
- if (!propertyName) {
- // Don't rename at `export { default } from "m";`. (but do continue to search for imports of the re-export)
- if (!(state.options.use === 2 /* Rename */ && (name.escapedText === "default" /* Default */))) {
- addRef();
- }
- }
- else if (referenceLocation === propertyName) {
- // For `export { foo as bar } from "baz"`, "`foo`" will be added from the singleReferences for import searches of the original export.
- // For `export { foo as bar };`, where `foo` is a local, so add it now.
- if (!exportDeclaration.moduleSpecifier) {
- addRef();
- }
- if (addReferencesHere && state.options.use !== 2 /* Rename */ && state.markSeenReExportRHS(name)) {
- addReference(name, ts.Debug.checkDefined(exportSpecifier.symbol), state);
- }
- }
- else {
- if (state.markSeenReExportRHS(referenceLocation)) {
- addRef();
- }
- }
- // For `export { foo as bar }`, rename `foo`, but not `bar`.
- if (!isForRenameWithPrefixAndSuffixText(state.options) || alwaysGetReferences) {
- var isDefaultExport = referenceLocation.originalKeywordKind === 84 /* DefaultKeyword */
- || exportSpecifier.name.originalKeywordKind === 84 /* DefaultKeyword */;
- var exportKind = isDefaultExport ? 1 /* Default */ : 0 /* Named */;
- var exportSymbol = ts.Debug.checkDefined(exportSpecifier.symbol);
- var exportInfo = FindAllReferences.getExportInfo(exportSymbol, exportKind, state.checker);
- if (exportInfo) {
- searchForImportsOfExport(referenceLocation, exportSymbol, exportInfo, state);
- }
- }
- // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`.
- if (search.comingFrom !== 1 /* Export */ && exportDeclaration.moduleSpecifier && !propertyName && !isForRenameWithPrefixAndSuffixText(state.options)) {
- var imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
- if (imported)
- searchForImportedSymbol(imported, state);
- }
- function addRef() {
- if (addReferencesHere)
- addReference(referenceLocation, localSymbol, state);
- }
- }
- function getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, checker) {
- return isExportSpecifierAlias(referenceLocation, exportSpecifier) && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier) || referenceSymbol;
- }
- function isExportSpecifierAlias(referenceLocation, exportSpecifier) {
- var parent = exportSpecifier.parent, propertyName = exportSpecifier.propertyName, name = exportSpecifier.name;
- ts.Debug.assert(propertyName === referenceLocation || name === referenceLocation);
- if (propertyName) {
- // Given `export { foo as bar } [from "someModule"]`: It's an alias at `foo`, but at `bar` it's a new symbol.
- return propertyName === referenceLocation;
- }
- else {
- // `export { foo } from "foo"` is a re-export.
- // `export { foo };` is not a re-export, it creates an alias for the local variable `foo`.
- return !parent.parent.moduleSpecifier;
- }
- }
- function getImportOrExportReferences(referenceLocation, referenceSymbol, search, state) {
- var importOrExport = FindAllReferences.getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === 1 /* Export */);
- if (!importOrExport)
- return;
- var symbol = importOrExport.symbol;
- if (importOrExport.kind === 0 /* Import */) {
- if (!(isForRenameWithPrefixAndSuffixText(state.options))) {
- searchForImportedSymbol(symbol, state);
- }
- }
- else {
- searchForImportsOfExport(referenceLocation, symbol, importOrExport.exportInfo, state);
- }
- }
- function getReferenceForShorthandProperty(_a, search, state) {
- var flags = _a.flags, valueDeclaration = _a.valueDeclaration;
- var shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration);
- var name = valueDeclaration && ts.getNameOfDeclaration(valueDeclaration);
- /*
- * Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
- * has two meanings: property name and property value. Therefore when we do findAllReference at the position where
- * an identifier is declared, the language service should return the position of the variable declaration as well as
- * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
- * position of property accessing, the referenceEntry of such position will be handled in the first case.
- */
- if (!(flags & 33554432 /* Transient */) && name && search.includes(shorthandValueSymbol)) {
- addReference(name, shorthandValueSymbol, state);
- }
- }
- function addReference(referenceLocation, relatedSymbol, state) {
- var _a = "kind" in relatedSymbol ? relatedSymbol : { kind: undefined, symbol: relatedSymbol }, kind = _a.kind, symbol = _a.symbol; // eslint-disable-line no-in-operator
- var addRef = state.referenceAdder(symbol);
- if (state.options.implementations) {
- addImplementationReferences(referenceLocation, addRef, state);
- }
- else {
- addRef(referenceLocation, kind);
- }
- }
- /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */
- function addConstructorReferences(referenceLocation, sourceFile, search, state) {
- if (ts.isNewExpressionTarget(referenceLocation)) {
- addReference(referenceLocation, search.symbol, state);
- }
- var pusher = function () { return state.referenceAdder(search.symbol); };
- if (ts.isClassLike(referenceLocation.parent)) {
- ts.Debug.assert(referenceLocation.kind === 84 /* DefaultKeyword */ || referenceLocation.parent.name === referenceLocation);
- // This is the class declaration containing the constructor.
- findOwnConstructorReferences(search.symbol, sourceFile, pusher());
- }
- else {
- // If this class appears in `extends C`, then the extending class' "super" calls are references.
- var classExtending = tryGetClassByExtendingIdentifier(referenceLocation);
- if (classExtending) {
- findSuperConstructorAccesses(classExtending, pusher());
- findInheritedConstructorReferences(classExtending, state);
- }
- }
- }
- function addClassStaticThisReferences(referenceLocation, search, state) {
- addReference(referenceLocation, search.symbol, state);
- var classLike = referenceLocation.parent;
- if (state.options.use === 2 /* Rename */ || !ts.isClassLike(classLike))
- return;
- ts.Debug.assert(classLike.name === referenceLocation);
- var addRef = state.referenceAdder(search.symbol);
- for (var _i = 0, _a = classLike.members; _i < _a.length; _i++) {
- var member = _a[_i];
- if (!(ts.isMethodOrAccessor(member) && ts.hasModifier(member, 32 /* Static */))) {
- continue;
- }
- if (member.body) {
- member.body.forEachChild(function cb(node) {
- if (node.kind === 104 /* ThisKeyword */) {
- addRef(node);
- }
- else if (!ts.isFunctionLike(node) && !ts.isClassLike(node)) {
- node.forEachChild(cb);
- }
- });
- }
- }
- }
- /**
- * `classSymbol` is the class where the constructor was defined.
- * Reference the constructor and all calls to `new this()`.
- */
- function findOwnConstructorReferences(classSymbol, sourceFile, addNode) {
- var constructorSymbol = getClassConstructorSymbol(classSymbol);
- if (constructorSymbol && constructorSymbol.declarations) {
- for (var _i = 0, _a = constructorSymbol.declarations; _i < _a.length; _i++) {
- var decl = _a[_i];
- var ctrKeyword = ts.findChildOfKind(decl, 129 /* ConstructorKeyword */, sourceFile);
- ts.Debug.assert(decl.kind === 162 /* Constructor */ && !!ctrKeyword);
- addNode(ctrKeyword);
- }
- }
- if (classSymbol.exports) {
- classSymbol.exports.forEach(function (member) {
- var decl = member.valueDeclaration;
- if (decl && decl.kind === 161 /* MethodDeclaration */) {
- var body = decl.body;
- if (body) {
- forEachDescendantOfKind(body, 104 /* ThisKeyword */, function (thisKeyword) {
- if (ts.isNewExpressionTarget(thisKeyword)) {
- addNode(thisKeyword);
- }
- });
- }
- }
- });
- }
- }
- function getClassConstructorSymbol(classSymbol) {
- return classSymbol.members && classSymbol.members.get("__constructor" /* Constructor */);
- }
- /** Find references to `super` in the constructor of an extending class. */
- function findSuperConstructorAccesses(classDeclaration, addNode) {
- var constructor = getClassConstructorSymbol(classDeclaration.symbol);
- if (!(constructor && constructor.declarations)) {
- return;
- }
- for (var _i = 0, _a = constructor.declarations; _i < _a.length; _i++) {
- var decl = _a[_i];
- ts.Debug.assert(decl.kind === 162 /* Constructor */);
- var body = decl.body;
- if (body) {
- forEachDescendantOfKind(body, 102 /* SuperKeyword */, function (node) {
- if (ts.isCallExpressionTarget(node)) {
- addNode(node);
- }
- });
- }
- }
- }
- function hasOwnConstructor(classDeclaration) {
- return !!getClassConstructorSymbol(classDeclaration.symbol);
- }
- function findInheritedConstructorReferences(classDeclaration, state) {
- if (hasOwnConstructor(classDeclaration))
- return;
- var classSymbol = classDeclaration.symbol;
- var search = state.createSearch(/*location*/ undefined, classSymbol, /*comingFrom*/ undefined);
- getReferencesInContainerOrFiles(classSymbol, state, search);
- }
- function addImplementationReferences(refNode, addReference, state) {
- // Check if we found a function/propertyAssignment/method with an implementation or initializer
- if (ts.isDeclarationName(refNode) && isImplementation(refNode.parent)) {
- addReference(refNode);
- return;
- }
- if (refNode.kind !== 75 /* Identifier */) {
- return;
- }
- if (refNode.parent.kind === 282 /* ShorthandPropertyAssignment */) {
- // Go ahead and dereference the shorthand assignment by going to its definition
- getReferenceEntriesForShorthandPropertyAssignment(refNode, state.checker, addReference);
- }
- // Check if the node is within an extends or implements clause
- var containingClass = getContainingClassIfInHeritageClause(refNode);
- if (containingClass) {
- addReference(containingClass);
- return;
- }
- // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface
- // Find the first node whose parent isn't a type node -- i.e., the highest type node.
- var typeNode = ts.findAncestor(refNode, function (a) { return !ts.isQualifiedName(a.parent) && !ts.isTypeNode(a.parent) && !ts.isTypeElement(a.parent); });
- var typeHavingNode = typeNode.parent;
- if (ts.hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) {
- if (ts.hasInitializer(typeHavingNode)) {
- addIfImplementation(typeHavingNode.initializer);
- }
- else if (ts.isFunctionLike(typeHavingNode) && typeHavingNode.body) {
- var body = typeHavingNode.body;
- if (body.kind === 223 /* Block */) {
- ts.forEachReturnStatement(body, function (returnStatement) {
- if (returnStatement.expression)
- addIfImplementation(returnStatement.expression);
- });
- }
- else {
- addIfImplementation(body);
- }
- }
- else if (ts.isAssertionExpression(typeHavingNode)) {
- addIfImplementation(typeHavingNode.expression);
- }
- }
- function addIfImplementation(e) {
- if (isImplementationExpression(e))
- addReference(e);
- }
- }
- function getContainingClassIfInHeritageClause(node) {
- return ts.isIdentifier(node) || ts.isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent)
- : ts.isExpressionWithTypeArguments(node) ? ts.tryCast(node.parent.parent, ts.isClassLike) : undefined;
- }
- /**
- * Returns true if this is an expression that can be considered an implementation
- */
- function isImplementationExpression(node) {
- switch (node.kind) {
- case 200 /* ParenthesizedExpression */:
- return isImplementationExpression(node.expression);
- case 202 /* ArrowFunction */:
- case 201 /* FunctionExpression */:
- case 193 /* ObjectLiteralExpression */:
- case 214 /* ClassExpression */:
- case 192 /* ArrayLiteralExpression */:
- return true;
- default:
- return false;
- }
- }
- /**
- * Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol
- * is an interface, determines if some ancestor of the child symbol extends or inherits from it.
- * Also takes in a cache of previous results which makes this slightly more efficient and is
- * necessary to avoid potential loops like so:
- * class A extends B { }
- * class B extends A { }
- *
- * We traverse the AST rather than using the type checker because users are typically only interested
- * in explicit implementations of an interface/class when calling "Go to Implementation". Sibling
- * implementations of types that share a common ancestor with the type whose implementation we are
- * searching for need to be filtered out of the results. The type checker doesn't let us make the
- * distinction between structurally compatible implementations and explicit implementations, so we
- * must use the AST.
- *
- * @param symbol A class or interface Symbol
- * @param parent Another class or interface Symbol
- * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results
- */
- function explicitlyInheritsFrom(symbol, parent, cachedResults, checker) {
- if (symbol === parent) {
- return true;
- }
- var key = ts.getSymbolId(symbol) + "," + ts.getSymbolId(parent);
- var cached = cachedResults.get(key);
- if (cached !== undefined) {
- return cached;
- }
- // Set the key so that we don't infinitely recurse
- cachedResults.set(key, false);
- var inherits = !!symbol.declarations && symbol.declarations.some(function (declaration) {
- return ts.getAllSuperTypeNodes(declaration).some(function (typeReference) {
- var type = checker.getTypeAtLocation(typeReference);
- return !!type && !!type.symbol && explicitlyInheritsFrom(type.symbol, parent, cachedResults, checker);
- });
- });
- cachedResults.set(key, inherits);
- return inherits;
- }
- function getReferencesForSuperKeyword(superKeyword) {
- var searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false);
- if (!searchSpaceNode) {
- return undefined;
- }
- // Whether 'super' occurs in a static context within a class.
- var staticFlag = 32 /* Static */;
- switch (searchSpaceNode.kind) {
- case 159 /* PropertyDeclaration */:
- case 158 /* PropertySignature */:
- case 161 /* MethodDeclaration */:
- case 160 /* MethodSignature */:
- case 162 /* Constructor */:
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- staticFlag &= ts.getModifierFlags(searchSpaceNode);
- searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
- break;
- default:
- return undefined;
- }
- var sourceFile = searchSpaceNode.getSourceFile();
- var references = ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "super", searchSpaceNode), function (node) {
- if (node.kind !== 102 /* SuperKeyword */) {
- return;
- }
- var container = ts.getSuperContainer(node, /*stopOnFunctions*/ false);
- // If we have a 'super' container, we must have an enclosing class.
- // Now make sure the owning class is the same as the search-space
- // and has the same static qualifier as the original 'super's owner.
- return container && (32 /* Static */ & ts.getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol ? nodeEntry(node) : undefined;
- });
- return [{ definition: { type: 0 /* Symbol */, symbol: searchSpaceNode.symbol }, references: references }];
- }
- function isParameterName(node) {
- return node.kind === 75 /* Identifier */ && node.parent.kind === 156 /* Parameter */ && node.parent.name === node;
- }
- function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles, cancellationToken) {
- var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
- // Whether 'this' occurs in a static context within a class.
- var staticFlag = 32 /* Static */;
- switch (searchSpaceNode.kind) {
- case 161 /* MethodDeclaration */:
- case 160 /* MethodSignature */:
- if (ts.isObjectLiteralMethod(searchSpaceNode)) {
- break;
- }
- // falls through
- case 159 /* PropertyDeclaration */:
- case 158 /* PropertySignature */:
- case 162 /* Constructor */:
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- staticFlag &= ts.getModifierFlags(searchSpaceNode);
- searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
- break;
- case 290 /* SourceFile */:
- if (ts.isExternalModule(searchSpaceNode) || isParameterName(thisOrSuperKeyword)) {
- return undefined;
- }
- // falls through
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- break;
- // Computed properties in classes are not handled here because references to this are illegal,
- // so there is no point finding references to them.
- default:
- return undefined;
- }
- var references = ts.flatMap(searchSpaceNode.kind === 290 /* SourceFile */ ? sourceFiles : [searchSpaceNode.getSourceFile()], function (sourceFile) {
- cancellationToken.throwIfCancellationRequested();
- return getPossibleSymbolReferenceNodes(sourceFile, "this", ts.isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode).filter(function (node) {
- if (!ts.isThis(node)) {
- return false;
- }
- var container = ts.getThisContainer(node, /* includeArrowFunctions */ false);
- switch (searchSpaceNode.kind) {
- case 201 /* FunctionExpression */:
- case 244 /* FunctionDeclaration */:
- return searchSpaceNode.symbol === container.symbol;
- case 161 /* MethodDeclaration */:
- case 160 /* MethodSignature */:
- return ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol;
- case 214 /* ClassExpression */:
- case 245 /* ClassDeclaration */:
- // Make sure the container belongs to the same class
- // and has the appropriate static modifier from the original container.
- return container.parent && searchSpaceNode.symbol === container.parent.symbol && (ts.getModifierFlags(container) & 32 /* Static */) === staticFlag;
- case 290 /* SourceFile */:
- return container.kind === 290 /* SourceFile */ && !ts.isExternalModule(container) && !isParameterName(node);
- }
- });
- }).map(function (n) { return nodeEntry(n); });
- var thisParameter = ts.firstDefined(references, function (r) { return ts.isParameter(r.node.parent) ? r.node : undefined; });
- return [{
- definition: { type: 3 /* This */, node: thisParameter || thisOrSuperKeyword },
- references: references
- }];
- }
- function getReferencesForStringLiteral(node, sourceFiles, cancellationToken) {
- var references = ts.flatMap(sourceFiles, function (sourceFile) {
- cancellationToken.throwIfCancellationRequested();
- return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), function (ref) {
- return ts.isStringLiteral(ref) && ref.text === node.text ? nodeEntry(ref, 2 /* StringLiteral */) : undefined;
- });
- });
- return [{
- definition: { type: 4 /* String */, node: node },
- references: references
- }];
- }
- // For certain symbol kinds, we need to include other symbols in the search set.
- // This is not needed when searching for re-exports.
- function populateSearchSymbolSet(symbol, location, checker, isForRename, providePrefixAndSuffixText, implementations) {
- var result = [];
- forEachRelatedSymbol(symbol, location, checker, isForRename, !(isForRename && providePrefixAndSuffixText), function (sym, root, base) { result.push(base || root || sym); },
- /*allowBaseTypes*/ function () { return !implementations; });
- return result;
- }
- function forEachRelatedSymbol(symbol, location, checker, isForRenamePopulateSearchSymbolSet, onlyIncludeBindingElementAtReferenceLocation, cbSymbol, allowBaseTypes) {
- var containingObjectLiteralElement = ts.getContainingObjectLiteralElement(location);
- if (containingObjectLiteralElement) {
- /* Because in short-hand property assignment, location has two meaning : property name and as value of the property
- * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
- * property name and variable declaration of the identifier.
- * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service
- * should show both 'name' in 'obj' and 'name' in variable declaration
- * const name = "Foo";
- * const obj = { name };
- * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment
- * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration
- * will be included correctly.
- */
- var shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent); // gets the local symbol
- if (shorthandValueSymbol && isForRenamePopulateSearchSymbolSet) {
- // When renaming 'x' in `const o = { x }`, just rename the local variable, not the property.
- return cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, 3 /* SearchedLocalFoundProperty */);
- }
- // If the location is in a context sensitive location (i.e. in an object literal) try
- // to get a contextual type for it, and add the property symbol from the contextual
- // type to the search set
- var contextualType = checker.getContextualType(containingObjectLiteralElement.parent);
- var res_1 = contextualType && ts.firstDefined(ts.getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true), function (sym) { return fromRoot(sym, 4 /* SearchedPropertyFoundLocal */); });
- if (res_1)
- return res_1;
- // If the location is name of property symbol from object literal destructuring pattern
- // Search the property symbol
- // for ( { property: p2 } of elems) { }
- var propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker);
- var res1 = propertySymbol && cbSymbol(propertySymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, 4 /* SearchedPropertyFoundLocal */);
- if (res1)
- return res1;
- var res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, 3 /* SearchedLocalFoundProperty */);
- if (res2)
- return res2;
- }
- var aliasedSymbol = getMergedAliasedSymbolOfNamespaceExportDeclaration(location, symbol, checker);
- if (aliasedSymbol) {
- // In case of UMD module and global merging, search for global as well
- var res_2 = cbSymbol(aliasedSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, 1 /* Node */);
- if (res_2)
- return res_2;
- }
- var res = fromRoot(symbol);
- if (res)
- return res;
- if (symbol.valueDeclaration && ts.isParameterPropertyDeclaration(symbol.valueDeclaration, symbol.valueDeclaration.parent)) {
- // For a parameter property, now try on the other symbol (property if this was a parameter, parameter if this was a property).
- var paramProps = checker.getSymbolsOfParameterPropertyDeclaration(ts.cast(symbol.valueDeclaration, ts.isParameter), symbol.name);
- ts.Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & 1 /* FunctionScopedVariable */) && !!(paramProps[1].flags & 4 /* Property */)); // is [parameter, property]
- return fromRoot(symbol.flags & 1 /* FunctionScopedVariable */ ? paramProps[1] : paramProps[0]);
- }
- var exportSpecifier = ts.getDeclarationOfKind(symbol, 263 /* ExportSpecifier */);
- if (!isForRenamePopulateSearchSymbolSet || exportSpecifier && !exportSpecifier.propertyName) {
- var localSymbol = exportSpecifier && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
- if (localSymbol) {
- var res_3 = cbSymbol(localSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, 1 /* Node */);
- if (res_3)
- return res_3;
- }
- }
- // symbolAtLocation for a binding element is the local symbol. See if the search symbol is the property.
- // Don't do this when populating search set for a rename when prefix and suffix text will be provided -- just rename the local.
- if (!isForRenamePopulateSearchSymbolSet) {
- var bindingElementPropertySymbol = void 0;
- if (onlyIncludeBindingElementAtReferenceLocation) {
- bindingElementPropertySymbol = ts.isObjectBindingElementWithoutPropertyName(location.parent) ? ts.getPropertySymbolFromBindingElement(checker, location.parent) : undefined;
- }
- else {
- bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
- }
- return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, 4 /* SearchedPropertyFoundLocal */);
- }
- ts.Debug.assert(isForRenamePopulateSearchSymbolSet);
- // due to the above assert and the arguments at the uses of this function,
- // (onlyIncludeBindingElementAtReferenceLocation <=> !providePrefixAndSuffixTextForRename) holds
- var includeOriginalSymbolOfBindingElement = onlyIncludeBindingElementAtReferenceLocation;
- if (includeOriginalSymbolOfBindingElement) {
- var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
- return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, 4 /* SearchedPropertyFoundLocal */);
- }
- function fromRoot(sym, kind) {
- // If this is a union property:
- // - In populateSearchSymbolsSet we will add all the symbols from all its source symbols in all unioned types.
- // - In findRelatedSymbol, we will just use the union symbol if any source symbol is included in the search.
- // If the symbol is an instantiation from a another symbol (e.g. widened symbol):
- // - In populateSearchSymbolsSet, add the root the list
- // - In findRelatedSymbol, return the source symbol if that is in the search. (Do not return the instantiation symbol.)
- return ts.firstDefined(checker.getRootSymbols(sym), function (rootSymbol) {
- return cbSymbol(sym, rootSymbol, /*baseSymbol*/ undefined, kind)
- // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
- || (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */) && allowBaseTypes(rootSymbol)
- ? ts.getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, function (base) { return cbSymbol(sym, rootSymbol, base, kind); })
- : undefined);
- });
- }
- function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker) {
- var bindingElement = ts.getDeclarationOfKind(symbol, 191 /* BindingElement */);
- if (bindingElement && ts.isObjectBindingElementWithoutPropertyName(bindingElement)) {
- return ts.getPropertySymbolFromBindingElement(checker, bindingElement);
- }
- }
- }
- function getRelatedSymbol(search, referenceSymbol, referenceLocation, state) {
- var checker = state.checker;
- return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false,
- /*onlyIncludeBindingElementAtReferenceLocation*/ state.options.use !== 2 /* Rename */ || !!state.options.providePrefixAndSuffixTextForRename, function (sym, rootSymbol, baseSymbol, kind) { return search.includes(baseSymbol || rootSymbol || sym)
- // For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol.
- ? { symbol: rootSymbol && !(ts.getCheckFlags(sym) & 6 /* Synthetic */) ? rootSymbol : sym, kind: kind }
- : undefined; },
- /*allowBaseTypes*/ function (rootSymbol) {
- return !(search.parents && !search.parents.some(function (parent) { return explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker); }));
- });
- }
- /**
- * Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
- * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
- * then we need to widen the search to include type positions as well.
- * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
- * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
- * do not intersect in any of the three spaces.
- */
- function getIntersectingMeaningFromDeclarations(node, symbol) {
- var meaning = ts.getMeaningFromLocation(node);
- var declarations = symbol.declarations;
- if (declarations) {
- var lastIterationMeaning = void 0;
- do {
- // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module]
- // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module
- // intersects with the class in the value space.
- // To achieve that we will keep iterating until the result stabilizes.
- // Remember the last meaning
- lastIterationMeaning = meaning;
- for (var _i = 0, declarations_2 = declarations; _i < declarations_2.length; _i++) {
- var declaration = declarations_2[_i];
- var declarationMeaning = ts.getMeaningFromDeclaration(declaration);
- if (declarationMeaning & meaning) {
- meaning |= declarationMeaning;
- }
- }
- } while (meaning !== lastIterationMeaning);
- }
- return meaning;
- }
- Core.getIntersectingMeaningFromDeclarations = getIntersectingMeaningFromDeclarations;
- function isImplementation(node) {
- return !!(node.flags & 8388608 /* Ambient */) ? !(ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) :
- (ts.isVariableLike(node) ? ts.hasInitializer(node) :
- ts.isFunctionLikeDeclaration(node) ? !!node.body :
- ts.isClassLike(node) || ts.isModuleOrEnumDeclaration(node));
- }
- function getReferenceEntriesForShorthandPropertyAssignment(node, checker, addReference) {
- var refSymbol = checker.getSymbolAtLocation(node);
- var shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration);
- if (shorthandSymbol) {
- for (var _i = 0, _a = shorthandSymbol.getDeclarations(); _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (ts.getMeaningFromDeclaration(declaration) & 1 /* Value */) {
- addReference(declaration);
- }
- }
- }
- }
- Core.getReferenceEntriesForShorthandPropertyAssignment = getReferenceEntriesForShorthandPropertyAssignment;
- function forEachDescendantOfKind(node, kind, action) {
- ts.forEachChild(node, function (child) {
- if (child.kind === kind) {
- action(child);
- }
- forEachDescendantOfKind(child, kind, action);
- });
- }
- /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */
- function tryGetClassByExtendingIdentifier(node) {
- return ts.tryGetClassExtendingExpressionWithTypeArguments(ts.climbPastPropertyAccess(node).parent);
- }
- /**
- * If we are just looking for implementations and this is a property access expression, we need to get the
- * symbol of the local type of the symbol the property is being accessed on. This is because our search
- * symbol may have a different parent symbol if the local type's symbol does not declare the property
- * being accessed (i.e. it is declared in some parent class or interface)
- */
- function getParentSymbolsOfPropertyAccess(location, symbol, checker) {
- var propertyAccessExpression = ts.isRightSideOfPropertyAccess(location) ? location.parent : undefined;
- var lhsType = propertyAccessExpression && checker.getTypeAtLocation(propertyAccessExpression.expression);
- var res = ts.mapDefined(lhsType && (lhsType.isUnionOrIntersection() ? lhsType.types : lhsType.symbol === symbol.parent ? undefined : [lhsType]), function (t) {
- return t.symbol && t.symbol.flags & (32 /* Class */ | 64 /* Interface */) ? t.symbol : undefined;
- });
- return res.length === 0 ? undefined : res;
- }
- function isForRenameWithPrefixAndSuffixText(options) {
- return options.use === 2 /* Rename */ && options.providePrefixAndSuffixTextForRename;
- }
- })(Core = FindAllReferences.Core || (FindAllReferences.Core = {}));
- })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var CallHierarchy;
- (function (CallHierarchy) {
- /** Indictates whether a node is named function or class expression. */
- function isNamedExpression(node) {
- return (ts.isFunctionExpression(node) || ts.isClassExpression(node)) && ts.isNamedDeclaration(node);
- }
- /** Indicates whether a node is a function, arrow, or class expression assigned to a constant variable. */
- function isConstNamedExpression(node) {
- return (ts.isFunctionExpression(node) || ts.isArrowFunction(node) || ts.isClassExpression(node))
- && ts.isVariableDeclaration(node.parent)
- && node === node.parent.initializer
- && ts.isIdentifier(node.parent.name)
- && !!(ts.getCombinedNodeFlags(node.parent) & 2 /* Const */);
- }
- /**
- * Indicates whether a node could possibly be a call hierarchy declaration.
- *
- * See `resolveCallHierarchyDeclaration` for the specific rules.
- */
- function isPossibleCallHierarchyDeclaration(node) {
- return ts.isSourceFile(node)
- || ts.isModuleDeclaration(node)
- || ts.isFunctionDeclaration(node)
- || ts.isFunctionExpression(node)
- || ts.isClassDeclaration(node)
- || ts.isClassExpression(node)
- || ts.isMethodDeclaration(node)
- || ts.isMethodSignature(node)
- || ts.isGetAccessorDeclaration(node)
- || ts.isSetAccessorDeclaration(node);
- }
- /**
- * Indicates whether a node is a valid a call hierarchy declaration.
- *
- * See `resolveCallHierarchyDeclaration` for the specific rules.
- */
- function isValidCallHierarchyDeclaration(node) {
- return ts.isSourceFile(node)
- || ts.isModuleDeclaration(node) && ts.isIdentifier(node.name)
- || ts.isFunctionDeclaration(node)
- || ts.isClassDeclaration(node)
- || ts.isMethodDeclaration(node)
- || ts.isMethodSignature(node)
- || ts.isGetAccessorDeclaration(node)
- || ts.isSetAccessorDeclaration(node)
- || isNamedExpression(node)
- || isConstNamedExpression(node);
- }
- /** Gets the node that can be used as a reference to a call hierarchy declaration. */
- function getCallHierarchyDeclarationReferenceNode(node) {
- if (ts.isSourceFile(node))
- return node;
- if (ts.isNamedDeclaration(node))
- return node.name;
- if (isConstNamedExpression(node))
- return node.parent.name;
- return ts.Debug.checkDefined(node.modifiers && ts.find(node.modifiers, isDefaultModifier));
- }
- function isDefaultModifier(node) {
- return node.kind === 84 /* DefaultKeyword */;
- }
- /** Gets the symbol for a call hierarchy declaration. */
- function getSymbolOfCallHierarchyDeclaration(typeChecker, node) {
- var location = getCallHierarchyDeclarationReferenceNode(node);
- return location && typeChecker.getSymbolAtLocation(location);
- }
- /** Gets the text and range for the name of a call hierarchy declaration. */
- function getCallHierarchyItemName(program, node) {
- if (ts.isSourceFile(node)) {
- return { text: node.fileName, pos: 0, end: 0 };
- }
- if ((ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node)) && !ts.isNamedDeclaration(node)) {
- var defaultModifier = node.modifiers && ts.find(node.modifiers, isDefaultModifier);
- if (defaultModifier) {
- return { text: "default", pos: defaultModifier.getStart(), end: defaultModifier.getEnd() };
- }
- }
- var declName = isConstNamedExpression(node) ? node.parent.name :
- ts.Debug.checkDefined(ts.getNameOfDeclaration(node), "Expected call hierarchy item to have a name");
- var text = ts.isIdentifier(declName) ? ts.idText(declName) :
- ts.isStringOrNumericLiteralLike(declName) ? declName.text :
- ts.isComputedPropertyName(declName) ?
- ts.isStringOrNumericLiteralLike(declName.expression) ? declName.expression.text :
- undefined :
- undefined;
- if (text === undefined) {
- var typeChecker = program.getTypeChecker();
- var symbol = typeChecker.getSymbolAtLocation(declName);
- if (symbol) {
- text = typeChecker.symbolToString(symbol, node);
- }
- }
- if (text === undefined) {
- // get the text from printing the node on a single line without comments...
- var printer_1 = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
- text = ts.usingSingleLineStringWriter(function (writer) { return printer_1.writeNode(4 /* Unspecified */, node, node.getSourceFile(), writer); });
- }
- return { text: text, pos: declName.getStart(), end: declName.getEnd() };
- }
- function findImplementation(typeChecker, node) {
- if (node.body) {
- return node;
- }
- if (ts.isConstructorDeclaration(node)) {
- return ts.getFirstConstructorWithBody(node.parent);
- }
- if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)) {
- var symbol = getSymbolOfCallHierarchyDeclaration(typeChecker, node);
- if (symbol && symbol.valueDeclaration && ts.isFunctionLikeDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.body) {
- return symbol.valueDeclaration;
- }
- return undefined;
- }
- return node;
- }
- function findAllInitialDeclarations(typeChecker, node) {
- var symbol = getSymbolOfCallHierarchyDeclaration(typeChecker, node);
- var declarations;
- if (symbol && symbol.declarations) {
- var indices = ts.indicesOf(symbol.declarations);
- var keys_1 = ts.map(symbol.declarations, function (decl) { return ({ file: decl.getSourceFile().fileName, pos: decl.pos }); });
- indices.sort(function (a, b) { return ts.compareStringsCaseSensitive(keys_1[a].file, keys_1[b].file) || keys_1[a].pos - keys_1[b].pos; });
- var sortedDeclarations = ts.map(indices, function (i) { return symbol.declarations[i]; });
- var lastDecl = void 0;
- for (var _i = 0, sortedDeclarations_1 = sortedDeclarations; _i < sortedDeclarations_1.length; _i++) {
- var decl = sortedDeclarations_1[_i];
- if (isValidCallHierarchyDeclaration(decl)) {
- if (!lastDecl || lastDecl.parent !== decl.parent || lastDecl.end !== decl.pos) {
- declarations = ts.append(declarations, decl);
- }
- lastDecl = decl;
- }
- }
- }
- return declarations;
- }
- /** Find the implementation or the first declaration for a call hierarchy declaration. */
- function findImplementationOrAllInitialDeclarations(typeChecker, node) {
- var _a, _b, _c;
- if (ts.isFunctionLikeDeclaration(node)) {
- return (_b = (_a = findImplementation(typeChecker, node)) !== null && _a !== void 0 ? _a : findAllInitialDeclarations(typeChecker, node)) !== null && _b !== void 0 ? _b : node;
- }
- return (_c = findAllInitialDeclarations(typeChecker, node)) !== null && _c !== void 0 ? _c : node;
- }
- /** Resolves the call hierarchy declaration for a node. */
- function resolveCallHierarchyDeclaration(program, location) {
- // A call hierarchy item must refer to either a SourceFile, Module Declaration, or something intrinsically callable that has a name:
- // - Class Declarations
- // - Class Expressions (with a name)
- // - Function Declarations
- // - Function Expressions (with a name or assigned to a const variable)
- // - Arrow Functions (assigned to a const variable)
- // - Constructors
- // - Methods
- // - Accessors
- //
- // If a call is contained in a non-named callable Node (function expression, arrow function, etc.), then
- // its containing `CallHierarchyItem` is a containing function or SourceFile that matches the above list.
- var typeChecker = program.getTypeChecker();
- var followingSymbol = false;
- while (true) {
- if (isValidCallHierarchyDeclaration(location)) {
- return findImplementationOrAllInitialDeclarations(typeChecker, location);
- }
- if (isPossibleCallHierarchyDeclaration(location)) {
- var ancestor = ts.findAncestor(location, isValidCallHierarchyDeclaration);
- return ancestor && findImplementationOrAllInitialDeclarations(typeChecker, ancestor);
- }
- if (ts.isDeclarationName(location)) {
- if (isValidCallHierarchyDeclaration(location.parent)) {
- return findImplementationOrAllInitialDeclarations(typeChecker, location.parent);
- }
- if (isPossibleCallHierarchyDeclaration(location.parent)) {
- var ancestor = ts.findAncestor(location.parent, isValidCallHierarchyDeclaration);
- return ancestor && findImplementationOrAllInitialDeclarations(typeChecker, ancestor);
- }
- if (ts.isVariableDeclaration(location.parent) && location.parent.initializer && isConstNamedExpression(location.parent.initializer)) {
- return location.parent.initializer;
- }
- return undefined;
- }
- if (ts.isConstructorDeclaration(location)) {
- if (isValidCallHierarchyDeclaration(location.parent)) {
- return location.parent;
- }
- return undefined;
- }
- if (!followingSymbol) {
- var symbol = typeChecker.getSymbolAtLocation(location);
- if (symbol) {
- if (symbol.flags & 2097152 /* Alias */) {
- symbol = typeChecker.getAliasedSymbol(symbol);
- }
- if (symbol.valueDeclaration) {
- followingSymbol = true;
- location = symbol.valueDeclaration;
- continue;
- }
- }
- }
- return undefined;
- }
- }
- CallHierarchy.resolveCallHierarchyDeclaration = resolveCallHierarchyDeclaration;
- /** Creates a `CallHierarchyItem` for a call hierarchy declaration. */
- function createCallHierarchyItem(program, node) {
- var sourceFile = node.getSourceFile();
- var name = getCallHierarchyItemName(program, node);
- var kind = ts.getNodeKind(node);
- var span = ts.createTextSpanFromBounds(ts.skipTrivia(sourceFile.text, node.getFullStart(), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true), node.getEnd());
- var selectionSpan = ts.createTextSpanFromBounds(name.pos, name.end);
- return { file: sourceFile.fileName, kind: kind, name: name.text, span: span, selectionSpan: selectionSpan };
- }
- CallHierarchy.createCallHierarchyItem = createCallHierarchyItem;
- function isDefined(x) {
- return x !== undefined;
- }
- function convertEntryToCallSite(entry) {
- if (entry.kind === 1 /* Node */) {
- var node = entry.node;
- if (ts.isCallOrNewExpressionTarget(node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
- || ts.isTaggedTemplateTag(node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
- || ts.isDecoratorTarget(node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
- || ts.isJsxOpeningLikeElementTagName(node, /*includeElementAccess*/ true, /*skipPastOuterExpressions*/ true)
- || ts.isRightSideOfPropertyAccess(node)
- || ts.isArgumentExpressionOfElementAccess(node)) {
- var sourceFile = node.getSourceFile();
- var ancestor = ts.findAncestor(node, isValidCallHierarchyDeclaration) || sourceFile;
- return { declaration: ancestor, range: ts.createTextRangeFromNode(node, sourceFile) };
- }
- }
- }
- function getCallSiteGroupKey(entry) {
- return "" + ts.getNodeId(entry.declaration);
- }
- function createCallHierarchyIncomingCall(from, fromSpans) {
- return { from: from, fromSpans: fromSpans };
- }
- function convertCallSiteGroupToIncomingCall(program, entries) {
- return createCallHierarchyIncomingCall(createCallHierarchyItem(program, entries[0].declaration), ts.map(entries, function (entry) { return ts.createTextSpanFromRange(entry.range); }));
- }
- /** Gets the call sites that call into the provided call hierarchy declaration. */
- function getIncomingCalls(program, declaration, cancellationToken) {
- // Source files and modules have no incoming calls.
- if (ts.isSourceFile(declaration) || ts.isModuleDeclaration(declaration)) {
- return [];
- }
- var location = getCallHierarchyDeclarationReferenceNode(declaration);
- var calls = ts.filter(ts.FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, program.getSourceFiles(), location, /*position*/ 0, { use: 1 /* References */ }, convertEntryToCallSite), isDefined);
- return calls ? ts.group(calls, getCallSiteGroupKey, function (entries) { return convertCallSiteGroupToIncomingCall(program, entries); }) : [];
- }
- CallHierarchy.getIncomingCalls = getIncomingCalls;
- function createCallSiteCollector(program, callSites) {
- function recordCallSite(node) {
- var target = ts.isTaggedTemplateExpression(node) ? node.tag :
- ts.isJsxOpeningLikeElement(node) ? node.tagName :
- ts.isAccessExpression(node) ? node :
- node.expression;
- var declaration = resolveCallHierarchyDeclaration(program, target);
- if (declaration) {
- var range = ts.createTextRangeFromNode(target, node.getSourceFile());
- if (ts.isArray(declaration)) {
- for (var _i = 0, declaration_1 = declaration; _i < declaration_1.length; _i++) {
- var decl = declaration_1[_i];
- callSites.push({ declaration: decl, range: range });
- }
- }
- else {
- callSites.push({ declaration: declaration, range: range });
- }
- }
- }
- function collect(node) {
- if (!node)
- return;
- if (node.flags & 8388608 /* Ambient */) {
- // do not descend into ambient nodes.
- return;
- }
- if (isValidCallHierarchyDeclaration(node)) {
- // do not descend into other call site declarations, other than class member names
- if (ts.isClassLike(node)) {
- for (var _i = 0, _a = node.members; _i < _a.length; _i++) {
- var member = _a[_i];
- if (member.name && ts.isComputedPropertyName(member.name)) {
- collect(member.name.expression);
- }
- }
- }
- return;
- }
- switch (node.kind) {
- case 75 /* Identifier */:
- case 253 /* ImportEqualsDeclaration */:
- case 254 /* ImportDeclaration */:
- case 260 /* ExportDeclaration */:
- case 246 /* InterfaceDeclaration */:
- case 247 /* TypeAliasDeclaration */:
- // do not descend into nodes that cannot contain callable nodes
- return;
- case 199 /* TypeAssertionExpression */:
- case 217 /* AsExpression */:
- // do not descend into the type side of an assertion
- collect(node.expression);
- return;
- case 242 /* VariableDeclaration */:
- case 156 /* Parameter */:
- // do not descend into the type of a variable or parameter declaration
- collect(node.name);
- collect(node.initializer);
- return;
- case 196 /* CallExpression */:
- // do not descend into the type arguments of a call expression
- recordCallSite(node);
- collect(node.expression);
- ts.forEach(node.arguments, collect);
- return;
- case 197 /* NewExpression */:
- // do not descend into the type arguments of a new expression
- recordCallSite(node);
- collect(node.expression);
- ts.forEach(node.arguments, collect);
- return;
- case 198 /* TaggedTemplateExpression */:
- // do not descend into the type arguments of a tagged template expression
- recordCallSite(node);
- collect(node.tag);
- collect(node.template);
- return;
- case 268 /* JsxOpeningElement */:
- case 267 /* JsxSelfClosingElement */:
- // do not descend into the type arguments of a JsxOpeningLikeElement
- recordCallSite(node);
- collect(node.tagName);
- collect(node.attributes);
- return;
- case 157 /* Decorator */:
- recordCallSite(node);
- collect(node.expression);
- return;
- case 194 /* PropertyAccessExpression */:
- case 195 /* ElementAccessExpression */:
- recordCallSite(node);
- ts.forEachChild(node, collect);
- break;
- }
- if (ts.isPartOfTypeNode(node)) {
- // do not descend into types
- return;
- }
- ts.forEachChild(node, collect);
- }
- return collect;
- }
- function collectCallSitesOfSourceFile(node, collect) {
- ts.forEach(node.statements, collect);
- }
- function collectCallSitesOfModuleDeclaration(node, collect) {
- if (!ts.hasModifier(node, 2 /* Ambient */) && node.body && ts.isModuleBlock(node.body)) {
- ts.forEach(node.body.statements, collect);
- }
- }
- function collectCallSitesOfFunctionLikeDeclaration(typeChecker, node, collect) {
- var implementation = findImplementation(typeChecker, node);
- if (implementation) {
- ts.forEach(implementation.parameters, collect);
- collect(implementation.body);
- }
- }
- function collectCallSitesOfClassLikeDeclaration(node, collect) {
- ts.forEach(node.decorators, collect);
- var heritage = ts.getClassExtendsHeritageElement(node);
- if (heritage) {
- collect(heritage.expression);
- }
- for (var _i = 0, _a = node.members; _i < _a.length; _i++) {
- var member = _a[_i];
- ts.forEach(member.decorators, collect);
- if (ts.isPropertyDeclaration(member)) {
- collect(member.initializer);
- }
- else if (ts.isConstructorDeclaration(member) && member.body) {
- ts.forEach(member.parameters, collect);
- collect(member.body);
- }
- }
- }
- function collectCallSites(program, node) {
- var callSites = [];
- var collect = createCallSiteCollector(program, callSites);
- switch (node.kind) {
- case 290 /* SourceFile */:
- collectCallSitesOfSourceFile(node, collect);
- break;
- case 249 /* ModuleDeclaration */:
- collectCallSitesOfModuleDeclaration(node, collect);
- break;
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 202 /* ArrowFunction */:
- case 161 /* MethodDeclaration */:
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- collectCallSitesOfFunctionLikeDeclaration(program.getTypeChecker(), node, collect);
- break;
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- collectCallSitesOfClassLikeDeclaration(node, collect);
- break;
- default:
- ts.Debug.assertNever(node);
- }
- return callSites;
- }
- function createCallHierarchyOutgoingCall(to, fromSpans) {
- return { to: to, fromSpans: fromSpans };
- }
- function convertCallSiteGroupToOutgoingCall(program, entries) {
- return createCallHierarchyOutgoingCall(createCallHierarchyItem(program, entries[0].declaration), ts.map(entries, function (entry) { return ts.createTextSpanFromRange(entry.range); }));
- }
- /** Gets the call sites that call out of the provided call hierarchy declaration. */
- function getOutgoingCalls(program, declaration) {
- if (declaration.flags & 8388608 /* Ambient */ || ts.isMethodSignature(declaration)) {
- return [];
- }
- return ts.group(collectCallSites(program, declaration), getCallSiteGroupKey, function (entries) { return convertCallSiteGroupToOutgoingCall(program, entries); });
- }
- CallHierarchy.getOutgoingCalls = getOutgoingCalls;
- })(CallHierarchy = ts.CallHierarchy || (ts.CallHierarchy = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- function getEditsForFileRename(program, oldFileOrDirPath, newFileOrDirPath, host, formatContext, preferences, sourceMapper) {
- var useCaseSensitiveFileNames = ts.hostUsesCaseSensitiveFileNames(host);
- var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
- var oldToNew = getPathUpdater(oldFileOrDirPath, newFileOrDirPath, getCanonicalFileName, sourceMapper);
- var newToOld = getPathUpdater(newFileOrDirPath, oldFileOrDirPath, getCanonicalFileName, sourceMapper);
- return ts.textChanges.ChangeTracker.with({ host: host, formatContext: formatContext, preferences: preferences }, function (changeTracker) {
- updateTsconfigFiles(program, changeTracker, oldToNew, oldFileOrDirPath, newFileOrDirPath, host.getCurrentDirectory(), useCaseSensitiveFileNames);
- updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName);
- });
- }
- ts.getEditsForFileRename = getEditsForFileRename;
- // exported for tests
- function getPathUpdater(oldFileOrDirPath, newFileOrDirPath, getCanonicalFileName, sourceMapper) {
- var canonicalOldPath = getCanonicalFileName(oldFileOrDirPath);
- return function (path) {
- var originalPath = sourceMapper && sourceMapper.tryGetSourcePosition({ fileName: path, pos: 0 });
- var updatedPath = getUpdatedPath(originalPath ? originalPath.fileName : path);
- return originalPath
- ? updatedPath === undefined ? undefined : makeCorrespondingRelativeChange(originalPath.fileName, updatedPath, path, getCanonicalFileName)
- : updatedPath;
- };
- function getUpdatedPath(pathToUpdate) {
- if (getCanonicalFileName(pathToUpdate) === canonicalOldPath)
- return newFileOrDirPath;
- var suffix = ts.tryRemoveDirectoryPrefix(pathToUpdate, canonicalOldPath, getCanonicalFileName);
- return suffix === undefined ? undefined : newFileOrDirPath + "/" + suffix;
- }
- }
- ts.getPathUpdater = getPathUpdater;
- // Relative path from a0 to b0 should be same as relative path from a1 to b1. Returns b1.
- function makeCorrespondingRelativeChange(a0, b0, a1, getCanonicalFileName) {
- var rel = ts.getRelativePathFromFile(a0, b0, getCanonicalFileName);
- return combinePathsSafe(ts.getDirectoryPath(a1), rel);
- }
- function updateTsconfigFiles(program, changeTracker, oldToNew, oldFileOrDirPath, newFileOrDirPath, currentDirectory, useCaseSensitiveFileNames) {
- var configFile = program.getCompilerOptions().configFile;
- if (!configFile)
- return;
- var configDir = ts.getDirectoryPath(configFile.fileName);
- var jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(configFile);
- if (!jsonObjectLiteral)
- return;
- forEachProperty(jsonObjectLiteral, function (property, propertyName) {
- switch (propertyName) {
- case "files":
- case "include":
- case "exclude": {
- var foundExactMatch = updatePaths(property);
- if (!foundExactMatch && propertyName === "include" && ts.isArrayLiteralExpression(property.initializer)) {
- var includes = ts.mapDefined(property.initializer.elements, function (e) { return ts.isStringLiteral(e) ? e.text : undefined; });
- var matchers = ts.getFileMatcherPatterns(configDir, /*excludes*/ [], includes, useCaseSensitiveFileNames, currentDirectory);
- // If there isn't some include for this, add a new one.
- if (ts.getRegexFromPattern(ts.Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(oldFileOrDirPath) &&
- !ts.getRegexFromPattern(ts.Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) {
- changeTracker.insertNodeAfter(configFile, ts.last(property.initializer.elements), ts.createStringLiteral(relativePath(newFileOrDirPath)));
- }
- }
- break;
- }
- case "compilerOptions":
- forEachProperty(property.initializer, function (property, propertyName) {
- var option = ts.getOptionFromName(propertyName);
- if (option && (option.isFilePath || option.type === "list" && option.element.isFilePath)) {
- updatePaths(property);
- }
- else if (propertyName === "paths") {
- forEachProperty(property.initializer, function (pathsProperty) {
- if (!ts.isArrayLiteralExpression(pathsProperty.initializer))
- return;
- for (var _i = 0, _a = pathsProperty.initializer.elements; _i < _a.length; _i++) {
- var e = _a[_i];
- tryUpdateString(e);
- }
- });
- }
- });
- break;
- }
- });
- function updatePaths(property) {
- // Type annotation needed due to #7294
- var elements = ts.isArrayLiteralExpression(property.initializer) ? property.initializer.elements : [property.initializer];
- var foundExactMatch = false;
- for (var _i = 0, elements_1 = elements; _i < elements_1.length; _i++) {
- var element = elements_1[_i];
- foundExactMatch = tryUpdateString(element) || foundExactMatch;
- }
- return foundExactMatch;
- }
- function tryUpdateString(element) {
- if (!ts.isStringLiteral(element))
- return false;
- var elementFileName = combinePathsSafe(configDir, element.text);
- var updated = oldToNew(elementFileName);
- if (updated !== undefined) {
- changeTracker.replaceRangeWithText(configFile, createStringRange(element, configFile), relativePath(updated));
- return true;
- }
- return false;
- }
- function relativePath(path) {
- return ts.getRelativePathFromDirectory(configDir, path, /*ignoreCase*/ !useCaseSensitiveFileNames);
- }
- }
- function updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName) {
- var allFiles = program.getSourceFiles();
- var _loop_4 = function (sourceFile) {
- var newFromOld = oldToNew(sourceFile.path);
- var newImportFromPath = newFromOld !== undefined ? newFromOld : sourceFile.path;
- var newImportFromDirectory = ts.getDirectoryPath(newImportFromPath);
- var oldFromNew = newToOld(sourceFile.fileName);
- var oldImportFromPath = oldFromNew || sourceFile.fileName;
- var oldImportFromDirectory = ts.getDirectoryPath(oldImportFromPath);
- var importingSourceFileMoved = newFromOld !== undefined || oldFromNew !== undefined;
- updateImportsWorker(sourceFile, changeTracker, function (referenceText) {
- if (!ts.pathIsRelative(referenceText))
- return undefined;
- var oldAbsolute = combinePathsSafe(oldImportFromDirectory, referenceText);
- var newAbsolute = oldToNew(oldAbsolute);
- return newAbsolute === undefined ? undefined : ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(newImportFromDirectory, newAbsolute, getCanonicalFileName));
- }, function (importLiteral) {
- var importedModuleSymbol = program.getTypeChecker().getSymbolAtLocation(importLiteral);
- // No need to update if it's an ambient module^M
- if (importedModuleSymbol && importedModuleSymbol.declarations.some(function (d) { return ts.isAmbientModule(d); }))
- return undefined;
- var toImport = oldFromNew !== undefined
- // If we're at the new location (file was already renamed), need to redo module resolution starting from the old location.
- // TODO:GH#18217
- ? getSourceFileToImportFromResolved(ts.resolveModuleName(importLiteral.text, oldImportFromPath, program.getCompilerOptions(), host), oldToNew, allFiles)
- : getSourceFileToImport(importedModuleSymbol, importLiteral, sourceFile, program, host, oldToNew);
- // Need an update if the imported file moved, or the importing file moved and was using a relative path.
- return toImport !== undefined && (toImport.updated || (importingSourceFileMoved && ts.pathIsRelative(importLiteral.text)))
- ? ts.moduleSpecifiers.updateModuleSpecifier(program.getCompilerOptions(), newImportFromPath, toImport.newFileName, ts.createModuleSpecifierResolutionHost(program, host), importLiteral.text)
- : undefined;
- });
- };
- for (var _i = 0, allFiles_1 = allFiles; _i < allFiles_1.length; _i++) {
- var sourceFile = allFiles_1[_i];
- _loop_4(sourceFile);
- }
- }
- function combineNormal(pathA, pathB) {
- return ts.normalizePath(ts.combinePaths(pathA, pathB));
- }
- function combinePathsSafe(pathA, pathB) {
- return ts.ensurePathIsNonModuleName(combineNormal(pathA, pathB));
- }
- function getSourceFileToImport(importedModuleSymbol, importLiteral, importingSourceFile, program, host, oldToNew) {
- if (importedModuleSymbol) {
- // `find` should succeed because we checked for ambient modules before calling this function.
- var oldFileName = ts.find(importedModuleSymbol.declarations, ts.isSourceFile).fileName;
- var newFileName = oldToNew(oldFileName);
- return newFileName === undefined ? { newFileName: oldFileName, updated: false } : { newFileName: newFileName, updated: true };
- }
- else {
- var resolved = host.resolveModuleNames
- ? host.getResolvedModuleWithFailedLookupLocationsFromCache && host.getResolvedModuleWithFailedLookupLocationsFromCache(importLiteral.text, importingSourceFile.fileName)
- : program.getResolvedModuleWithFailedLookupLocationsFromCache(importLiteral.text, importingSourceFile.fileName);
- return getSourceFileToImportFromResolved(resolved, oldToNew, program.getSourceFiles());
- }
- }
- function getSourceFileToImportFromResolved(resolved, oldToNew, sourceFiles) {
- // Search through all locations looking for a moved file, and only then test already existing files.
- // This is because if `a.ts` is compiled to `a.js` and `a.ts` is moved, we don't want to resolve anything to `a.js`, but to `a.ts`'s new location.
- if (!resolved)
- return undefined;
- // First try resolved module
- if (resolved.resolvedModule) {
- var result_2 = tryChange(resolved.resolvedModule.resolvedFileName);
- if (result_2)
- return result_2;
- }
- // Then failed lookups that are in the list of sources
- var result = ts.forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJsonExisting)
- // Then failed lookups except package.json since we dont want to touch them (only included ts/js files)
- || ts.forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJson);
- if (result)
- return result;
- // If nothing changed, then result is resolved module file thats not updated
- return resolved.resolvedModule && { newFileName: resolved.resolvedModule.resolvedFileName, updated: false };
- function tryChangeWithIgnoringPackageJsonExisting(oldFileName) {
- var newFileName = oldToNew(oldFileName);
- return newFileName && ts.find(sourceFiles, function (src) { return src.fileName === newFileName; })
- ? tryChangeWithIgnoringPackageJson(oldFileName) : undefined;
- }
- function tryChangeWithIgnoringPackageJson(oldFileName) {
- return !ts.endsWith(oldFileName, "/package.json") ? tryChange(oldFileName) : undefined;
- }
- function tryChange(oldFileName) {
- var newFileName = oldToNew(oldFileName);
- return newFileName && { newFileName: newFileName, updated: true };
- }
- }
- function updateImportsWorker(sourceFile, changeTracker, updateRef, updateImport) {
- for (var _i = 0, _a = sourceFile.referencedFiles || ts.emptyArray; _i < _a.length; _i++) { // TODO: GH#26162
- var ref = _a[_i];
- var updated = updateRef(ref.fileName);
- if (updated !== undefined && updated !== sourceFile.text.slice(ref.pos, ref.end))
- changeTracker.replaceRangeWithText(sourceFile, ref, updated);
- }
- for (var _b = 0, _c = sourceFile.imports; _b < _c.length; _b++) {
- var importStringLiteral = _c[_b];
- var updated = updateImport(importStringLiteral);
- if (updated !== undefined && updated !== importStringLiteral.text)
- changeTracker.replaceRangeWithText(sourceFile, createStringRange(importStringLiteral, sourceFile), updated);
- }
- }
- function createStringRange(node, sourceFile) {
- return ts.createRange(node.getStart(sourceFile) + 1, node.end - 1);
- }
- function forEachProperty(objectLiteral, cb) {
- if (!ts.isObjectLiteralExpression(objectLiteral))
- return;
- for (var _i = 0, _a = objectLiteral.properties; _i < _a.length; _i++) {
- var property = _a[_i];
- if (ts.isPropertyAssignment(property) && ts.isStringLiteral(property.name)) {
- cb(property, property.name.text);
- }
- }
- }
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var GoToDefinition;
- (function (GoToDefinition) {
- function getDefinitionAtPosition(program, sourceFile, position) {
- var reference = getReferenceAtPosition(sourceFile, position, program);
- if (reference) {
- return [getDefinitionInfoForFileReference(reference.fileName, reference.file.fileName)];
- }
- var node = ts.getTouchingPropertyName(sourceFile, position);
- if (node === sourceFile) {
- return undefined;
- }
- var parent = node.parent;
- var typeChecker = program.getTypeChecker();
- // Labels
- if (ts.isJumpStatementTarget(node)) {
- var label = ts.getTargetLabel(node.parent, node.text);
- return label ? [createDefinitionInfoFromName(typeChecker, label, "label" /* label */, node.text, /*containerName*/ undefined)] : undefined; // TODO: GH#18217
- }
- var symbol = getSymbol(node, typeChecker);
- // Could not find a symbol e.g. node is string or number keyword,
- // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
- if (!symbol) {
- return getDefinitionInfoForIndexSignatures(node, typeChecker);
- }
- var calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
- // Don't go to the component constructor definition for a JSX element, just go to the component definition.
- if (calledDeclaration && !(ts.isJsxOpeningLikeElement(node.parent) && isConstructorLike(calledDeclaration))) {
- var sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration);
- // For a function, if this is the original function definition, return just sigInfo.
- // If this is the original constructor definition, parent is the class.
- if (typeChecker.getRootSymbols(symbol).some(function (s) { return symbolMatchesSignature(s, calledDeclaration); }) ||
- // TODO: GH#25533 Following check shouldn't be necessary if 'require' is an alias
- symbol.declarations && symbol.declarations.some(function (d) { return ts.isVariableDeclaration(d) && !!d.initializer && ts.isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ false); })) {
- return [sigInfo];
- }
- else {
- var defs = getDefinitionFromSymbol(typeChecker, symbol, node, calledDeclaration) || ts.emptyArray;
- // For a 'super()' call, put the signature first, else put the variable first.
- return node.kind === 102 /* SuperKeyword */ ? __spreadArrays([sigInfo], defs) : __spreadArrays(defs, [sigInfo]);
- }
- }
- // Because name in short-hand property assignment has two different meanings: property name and property value,
- // using go-to-definition at such position should go to the variable declaration of the property value rather than
- // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition
- // is performed at the location of property access, we would like to go to definition of the property in the short-hand
- // assignment. This case and others are handled by the following code.
- if (node.parent.kind === 282 /* ShorthandPropertyAssignment */) {
- var shorthandSymbol_1 = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
- return shorthandSymbol_1 ? shorthandSymbol_1.declarations.map(function (decl) { return createDefinitionInfo(decl, typeChecker, shorthandSymbol_1, node); }) : [];
- }
- // If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the
- // declaration the symbol (which is itself), we should try to get to the original type of the ObjectBindingPattern
- // and return the property declaration for the referenced property.
- // For example:
- // import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo"
- //
- // function bar(onfulfilled: (value: T) => void) { //....}
- // interface Test {
- // pr/*destination*/op1: number
- // }
- // bar(({pr/*goto*/op1})=>{});
- if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) &&
- (node === (parent.propertyName || parent.name))) {
- var name_3 = ts.getNameFromPropertyName(node);
- var type = typeChecker.getTypeAtLocation(parent.parent);
- return name_3 === undefined ? ts.emptyArray : ts.flatMap(type.isUnion() ? type.types : [type], function (t) {
- var prop = t.getProperty(name_3);
- return prop && getDefinitionFromSymbol(typeChecker, prop, node);
- });
- }
- // If the current location we want to find its definition is in an object literal, try to get the contextual type for the
- // object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
- // For example
- // interface Props{
- // /*first*/prop1: number
- // prop2: boolean
- // }
- // function Foo(arg: Props) {}
- // Foo( { pr/*1*/op1: 10, prop2: true })
- var element = ts.getContainingObjectLiteralElement(node);
- if (element) {
- var contextualType = element && typeChecker.getContextualType(element.parent);
- if (contextualType) {
- return ts.flatMap(ts.getPropertySymbolsFromContextualType(element, typeChecker, contextualType, /*unionSymbolOk*/ false), function (propertySymbol) {
- return getDefinitionFromSymbol(typeChecker, propertySymbol, node);
- });
- }
- }
- return getDefinitionFromSymbol(typeChecker, symbol, node);
- }
- GoToDefinition.getDefinitionAtPosition = getDefinitionAtPosition;
- /**
- * True if we should not add definitions for both the signature symbol and the definition symbol.
- * True for `const |f = |() => 0`, false for `function |f() {} const |g = f;`.
- */
- function symbolMatchesSignature(s, calledDeclaration) {
- return s === calledDeclaration.symbol || s === calledDeclaration.symbol.parent ||
- !ts.isCallLikeExpression(calledDeclaration.parent) && s === calledDeclaration.parent.symbol;
- }
- function getReferenceAtPosition(sourceFile, position, program) {
- var referencePath = findReferenceInPosition(sourceFile.referencedFiles, position);
- if (referencePath) {
- var file = program.getSourceFileFromReference(sourceFile, referencePath);
- return file && { fileName: referencePath.fileName, file: file };
- }
- var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
- if (typeReferenceDirective) {
- var reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName);
- var file = reference && program.getSourceFile(reference.resolvedFileName); // TODO:GH#18217
- return file && { fileName: typeReferenceDirective.fileName, file: file };
- }
- var libReferenceDirective = findReferenceInPosition(sourceFile.libReferenceDirectives, position);
- if (libReferenceDirective) {
- var file = program.getLibFileFromReference(libReferenceDirective);
- return file && { fileName: libReferenceDirective.fileName, file: file };
- }
- return undefined;
- }
- GoToDefinition.getReferenceAtPosition = getReferenceAtPosition;
- /// Goto type
- function getTypeDefinitionAtPosition(typeChecker, sourceFile, position) {
- var node = ts.getTouchingPropertyName(sourceFile, position);
- if (node === sourceFile) {
- return undefined;
- }
- var symbol = typeChecker.getSymbolAtLocation(node);
- if (!symbol)
- return undefined;
- var typeAtLocation = typeChecker.getTypeOfSymbolAtLocation(symbol, node);
- var returnType = tryGetReturnTypeOfFunction(symbol, typeAtLocation, typeChecker);
- var fromReturnType = returnType && definitionFromType(returnType, typeChecker, node);
- // If a function returns 'void' or some other type with no definition, just return the function definition.
- return fromReturnType && fromReturnType.length !== 0 ? fromReturnType : definitionFromType(typeAtLocation, typeChecker, node);
- }
- GoToDefinition.getTypeDefinitionAtPosition = getTypeDefinitionAtPosition;
- function definitionFromType(type, checker, node) {
- return ts.flatMap(type.isUnion() && !(type.flags & 32 /* Enum */) ? type.types : [type], function (t) {
- return t.symbol && getDefinitionFromSymbol(checker, t.symbol, node);
- });
- }
- function tryGetReturnTypeOfFunction(symbol, type, checker) {
- // If the type is just a function's inferred type,
- // go-to-type should go to the return type instead, since go-to-definition takes you to the function anyway.
- if (type.symbol === symbol ||
- // At `const f = () => {}`, the symbol is `f` and the type symbol is at `() => {}`
- symbol.valueDeclaration && type.symbol && ts.isVariableDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.initializer === type.symbol.valueDeclaration) {
- var sigs = type.getCallSignatures();
- if (sigs.length === 1)
- return checker.getReturnTypeOfSignature(ts.first(sigs));
- }
- return undefined;
- }
- function getDefinitionAndBoundSpan(program, sourceFile, position) {
- var definitions = getDefinitionAtPosition(program, sourceFile, position);
- if (!definitions || definitions.length === 0) {
- return undefined;
- }
- // Check if position is on triple slash reference.
- var comment = findReferenceInPosition(sourceFile.referencedFiles, position) ||
- findReferenceInPosition(sourceFile.typeReferenceDirectives, position) ||
- findReferenceInPosition(sourceFile.libReferenceDirectives, position);
- if (comment) {
- return { definitions: definitions, textSpan: ts.createTextSpanFromRange(comment) };
- }
- var node = ts.getTouchingPropertyName(sourceFile, position);
- var textSpan = ts.createTextSpan(node.getStart(), node.getWidth());
- return { definitions: definitions, textSpan: textSpan };
- }
- GoToDefinition.getDefinitionAndBoundSpan = getDefinitionAndBoundSpan;
- // At 'x.foo', see if the type of 'x' has an index signature, and if so find its declarations.
- function getDefinitionInfoForIndexSignatures(node, checker) {
- if (!ts.isPropertyAccessExpression(node.parent) || node.parent.name !== node)
- return;
- var type = checker.getTypeAtLocation(node.parent.expression);
- return ts.mapDefined(type.isUnionOrIntersection() ? type.types : [type], function (nonUnionType) {
- var info = checker.getIndexInfoOfType(nonUnionType, 0 /* String */);
- return info && info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration);
- });
- }
- function getSymbol(node, checker) {
- var symbol = checker.getSymbolAtLocation(node);
- // If this is an alias, and the request came at the declaration location
- // get the aliased symbol instead. This allows for goto def on an import e.g.
- // import {A, B} from "mod";
- // to jump to the implementation directly.
- if (symbol && symbol.flags & 2097152 /* Alias */ && shouldSkipAlias(node, symbol.declarations[0])) {
- var aliased = checker.getAliasedSymbol(symbol);
- if (aliased.declarations) {
- return aliased;
- }
- }
- if (symbol && ts.isInJSFile(node)) {
- var requireCall = ts.forEach(symbol.declarations, function (d) { return ts.isVariableDeclaration(d) && !!d.initializer && ts.isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true) ? d.initializer : undefined; });
- if (requireCall) {
- var moduleSymbol = checker.getSymbolAtLocation(requireCall.arguments[0]);
- if (moduleSymbol) {
- return checker.resolveExternalModuleSymbol(moduleSymbol);
- }
- }
- }
- return symbol;
- }
- // Go to the original declaration for cases:
- //
- // (1) when the aliased symbol was declared in the location(parent).
- // (2) when the aliased symbol is originating from an import.
- //
- function shouldSkipAlias(node, declaration) {
- if (node.kind !== 75 /* Identifier */) {
- return false;
- }
- if (node.parent === declaration) {
- return true;
- }
- switch (declaration.kind) {
- case 255 /* ImportClause */:
- case 253 /* ImportEqualsDeclaration */:
- return true;
- case 258 /* ImportSpecifier */:
- return declaration.parent.kind === 257 /* NamedImports */;
- default:
- return false;
- }
- }
- function getDefinitionFromSymbol(typeChecker, symbol, node, declarationNode) {
- // There are cases when you extend a function by adding properties to it afterwards,
- // we want to strip those extra properties.
- // For deduping purposes, we also want to exclude any declarationNodes if provided.
- var filteredDeclarations = ts.filter(symbol.declarations, function (d) { return d !== declarationNode && (!ts.isAssignmentDeclaration(d) || d === symbol.valueDeclaration); }) || undefined;
- return getConstructSignatureDefinition() || getCallSignatureDefinition() || ts.map(filteredDeclarations, function (declaration) { return createDefinitionInfo(declaration, typeChecker, symbol, node); });
- function getConstructSignatureDefinition() {
- // Applicable only if we are in a new expression, or we are on a constructor declaration
- // and in either case the symbol has a construct signature definition, i.e. class
- if (symbol.flags & 32 /* Class */ && !(symbol.flags & (16 /* Function */ | 3 /* Variable */)) && (ts.isNewExpressionTarget(node) || node.kind === 129 /* ConstructorKeyword */)) {
- var cls = ts.find(filteredDeclarations, ts.isClassLike) || ts.Debug.fail("Expected declaration to have at least one class-like declaration");
- return getSignatureDefinition(cls.members, /*selectConstructors*/ true);
- }
- }
- function getCallSignatureDefinition() {
- return ts.isCallOrNewExpressionTarget(node) || ts.isNameOfFunctionDeclaration(node)
- ? getSignatureDefinition(filteredDeclarations, /*selectConstructors*/ false)
- : undefined;
- }
- function getSignatureDefinition(signatureDeclarations, selectConstructors) {
- if (!signatureDeclarations) {
- return undefined;
- }
- var declarations = signatureDeclarations.filter(selectConstructors ? ts.isConstructorDeclaration : ts.isFunctionLike);
- var declarationsWithBody = declarations.filter(function (d) { return !!d.body; });
- // declarations defined on the global scope can be defined on multiple files. Get all of them.
- return declarations.length
- ? declarationsWithBody.length !== 0
- ? declarationsWithBody.map(function (x) { return createDefinitionInfo(x, typeChecker, symbol, node); })
- : [createDefinitionInfo(ts.last(declarations), typeChecker, symbol, node)]
- : undefined;
- }
- }
- /** Creates a DefinitionInfo from a Declaration, using the declaration's name if possible. */
- function createDefinitionInfo(declaration, checker, symbol, node) {
- var symbolName = checker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
- var symbolKind = ts.SymbolDisplay.getSymbolKind(checker, symbol, node);
- var containerName = symbol.parent ? checker.symbolToString(symbol.parent, node) : "";
- return createDefinitionInfoFromName(checker, declaration, symbolKind, symbolName, containerName);
- }
- /** Creates a DefinitionInfo directly from the name of a declaration. */
- function createDefinitionInfoFromName(checker, declaration, symbolKind, symbolName, containerName) {
- var name = ts.getNameOfDeclaration(declaration) || declaration;
- var sourceFile = name.getSourceFile();
- var textSpan = ts.createTextSpanFromNode(name, sourceFile);
- return __assign(__assign({ fileName: sourceFile.fileName, textSpan: textSpan, kind: symbolKind, name: symbolName, containerKind: undefined, // TODO: GH#18217
- containerName: containerName }, ts.FindAllReferences.toContextSpan(textSpan, sourceFile, ts.FindAllReferences.getContextNode(declaration))), { isLocal: !checker.isDeclarationVisible(declaration) });
- }
- function createDefinitionFromSignatureDeclaration(typeChecker, decl) {
- return createDefinitionInfo(decl, typeChecker, decl.symbol, decl);
- }
- function findReferenceInPosition(refs, pos) {
- return ts.find(refs, function (ref) { return ts.textRangeContainsPositionInclusive(ref, pos); });
- }
- GoToDefinition.findReferenceInPosition = findReferenceInPosition;
- function getDefinitionInfoForFileReference(name, targetFileName) {
- return {
- fileName: targetFileName,
- textSpan: ts.createTextSpanFromBounds(0, 0),
- kind: "script" /* scriptElement */,
- name: name,
- containerName: undefined,
- containerKind: undefined,
- };
- }
- /** Returns a CallLikeExpression where `node` is the target being invoked. */
- function getAncestorCallLikeExpression(node) {
- var target = climbPastManyPropertyAccesses(node);
- var callLike = target.parent;
- return callLike && ts.isCallLikeExpression(callLike) && ts.getInvokedExpression(callLike) === target ? callLike : undefined;
- }
- function climbPastManyPropertyAccesses(node) {
- return ts.isRightSideOfPropertyAccess(node) ? climbPastManyPropertyAccesses(node.parent) : node;
- }
- function tryGetSignatureDeclaration(typeChecker, node) {
- var callLike = getAncestorCallLikeExpression(node);
- var signature = callLike && typeChecker.getResolvedSignature(callLike);
- // Don't go to a function type, go to the value having that type.
- return ts.tryCast(signature && signature.declaration, function (d) { return ts.isFunctionLike(d) && !ts.isFunctionTypeNode(d); });
- }
- function isConstructorLike(node) {
- switch (node.kind) {
- case 162 /* Constructor */:
- case 171 /* ConstructorType */:
- case 166 /* ConstructSignature */:
- return true;
- default:
- return false;
- }
- }
- })(GoToDefinition = ts.GoToDefinition || (ts.GoToDefinition = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var JsDoc;
- (function (JsDoc) {
- var jsDocTagNames = [
- "abstract",
- "access",
- "alias",
- "argument",
- "async",
- "augments",
- "author",
- "borrows",
- "callback",
- "class",
- "classdesc",
- "constant",
- "constructor",
- "constructs",
- "copyright",
- "default",
- "deprecated",
- "description",
- "emits",
- "enum",
- "event",
- "example",
- "exports",
- "extends",
- "external",
- "field",
- "file",
- "fileoverview",
- "fires",
- "function",
- "generator",
- "global",
- "hideconstructor",
- "host",
- "ignore",
- "implements",
- "inheritdoc",
- "inner",
- "instance",
- "interface",
- "kind",
- "lends",
- "license",
- "listens",
- "member",
- "memberof",
- "method",
- "mixes",
- "module",
- "name",
- "namespace",
- "override",
- "package",
- "param",
- "private",
- "property",
- "protected",
- "public",
- "readonly",
- "requires",
- "returns",
- "see",
- "since",
- "static",
- "summary",
- "template",
- "this",
- "throws",
- "todo",
- "tutorial",
- "type",
- "typedef",
- "var",
- "variation",
- "version",
- "virtual",
- "yields"
- ];
- var jsDocTagNameCompletionEntries;
- var jsDocTagCompletionEntries;
- function getJsDocCommentsFromDeclarations(declarations) {
- // Only collect doc comments from duplicate declarations once:
- // In case of a union property there might be same declaration multiple times
- // which only varies in type parameter
- // Eg. const a: Array | Array; a.length
- // The property length will have two declarations of property length coming
- // from Array - Array and Array
- var documentationComment = [];
- ts.forEachUnique(declarations, function (declaration) {
- for (var _i = 0, _a = getCommentHavingNodes(declaration); _i < _a.length; _i++) {
- var comment = _a[_i].comment;
- if (comment === undefined)
- continue;
- if (documentationComment.length) {
- documentationComment.push(ts.lineBreakPart());
- }
- documentationComment.push(ts.textPart(comment));
- }
- });
- return documentationComment;
- }
- JsDoc.getJsDocCommentsFromDeclarations = getJsDocCommentsFromDeclarations;
- function getCommentHavingNodes(declaration) {
- switch (declaration.kind) {
- case 317 /* JSDocParameterTag */:
- case 323 /* JSDocPropertyTag */:
- return [declaration];
- case 315 /* JSDocCallbackTag */:
- case 322 /* JSDocTypedefTag */:
- return [declaration, declaration.parent];
- default:
- return ts.getJSDocCommentsAndTags(declaration);
- }
- }
- function getJsDocTagsFromDeclarations(declarations) {
- // Only collect doc comments from duplicate declarations once.
- var tags = [];
- ts.forEachUnique(declarations, function (declaration) {
- for (var _i = 0, _a = ts.getJSDocTags(declaration); _i < _a.length; _i++) {
- var tag = _a[_i];
- tags.push({ name: tag.tagName.text, text: getCommentText(tag) });
- }
- });
- return tags;
- }
- JsDoc.getJsDocTagsFromDeclarations = getJsDocTagsFromDeclarations;
- function getCommentText(tag) {
- var comment = tag.comment;
- switch (tag.kind) {
- case 308 /* JSDocImplementsTag */:
- return withNode(tag.class);
- case 307 /* JSDocAugmentsTag */:
- return withNode(tag.class);
- case 321 /* JSDocTemplateTag */:
- return withList(tag.typeParameters);
- case 320 /* JSDocTypeTag */:
- return withNode(tag.typeExpression);
- case 322 /* JSDocTypedefTag */:
- case 315 /* JSDocCallbackTag */:
- case 323 /* JSDocPropertyTag */:
- case 317 /* JSDocParameterTag */:
- var name = tag.name;
- return name ? withNode(name) : comment;
- default:
- return comment;
- }
- function withNode(node) {
- return addComment(node.getText());
- }
- function withList(list) {
- return addComment(list.map(function (x) { return x.getText(); }).join(", "));
- }
- function addComment(s) {
- return comment === undefined ? s : s + " " + comment;
- }
- }
- function getJSDocTagNameCompletions() {
- return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = ts.map(jsDocTagNames, function (tagName) {
- return {
- name: tagName,
- kind: "keyword" /* keyword */,
- kindModifiers: "",
- sortText: "0",
- };
- }));
- }
- JsDoc.getJSDocTagNameCompletions = getJSDocTagNameCompletions;
- JsDoc.getJSDocTagNameCompletionDetails = getJSDocTagCompletionDetails;
- function getJSDocTagCompletions() {
- return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = ts.map(jsDocTagNames, function (tagName) {
- return {
- name: "@" + tagName,
- kind: "keyword" /* keyword */,
- kindModifiers: "",
- sortText: "0"
- };
- }));
- }
- JsDoc.getJSDocTagCompletions = getJSDocTagCompletions;
- function getJSDocTagCompletionDetails(name) {
- return {
- name: name,
- kind: "" /* unknown */,
- kindModifiers: "",
- displayParts: [ts.textPart(name)],
- documentation: ts.emptyArray,
- tags: undefined,
- codeActions: undefined,
- };
- }
- JsDoc.getJSDocTagCompletionDetails = getJSDocTagCompletionDetails;
- function getJSDocParameterNameCompletions(tag) {
- if (!ts.isIdentifier(tag.name)) {
- return ts.emptyArray;
- }
- var nameThusFar = tag.name.text;
- var jsdoc = tag.parent;
- var fn = jsdoc.parent;
- if (!ts.isFunctionLike(fn))
- return [];
- return ts.mapDefined(fn.parameters, function (param) {
- if (!ts.isIdentifier(param.name))
- return undefined;
- var name = param.name.text;
- if (jsdoc.tags.some(function (t) { return t !== tag && ts.isJSDocParameterTag(t) && ts.isIdentifier(t.name) && t.name.escapedText === name; }) // TODO: GH#18217
- || nameThusFar !== undefined && !ts.startsWith(name, nameThusFar)) {
- return undefined;
- }
- return { name: name, kind: "parameter" /* parameterElement */, kindModifiers: "", sortText: "0" };
- });
- }
- JsDoc.getJSDocParameterNameCompletions = getJSDocParameterNameCompletions;
- function getJSDocParameterNameCompletionDetails(name) {
- return {
- name: name,
- kind: "parameter" /* parameterElement */,
- kindModifiers: "",
- displayParts: [ts.textPart(name)],
- documentation: ts.emptyArray,
- tags: undefined,
- codeActions: undefined,
- };
- }
- JsDoc.getJSDocParameterNameCompletionDetails = getJSDocParameterNameCompletionDetails;
- /**
- * Checks if position points to a valid position to add JSDoc comments, and if so,
- * returns the appropriate template. Otherwise returns an empty string.
- * Valid positions are
- * - outside of comments, statements, and expressions, and
- * - preceding a:
- * - function/constructor/method declaration
- * - class declarations
- * - variable statements
- * - namespace declarations
- * - interface declarations
- * - method signatures
- * - type alias declarations
- *
- * Hosts should ideally check that:
- * - The line is all whitespace up to 'position' before performing the insertion.
- * - If the keystroke sequence "/\*\*" induced the call, we also check that the next
- * non-whitespace character is '*', which (approximately) indicates whether we added
- * the second '*' to complete an existing (JSDoc) comment.
- * @param fileName The file in which to perform the check.
- * @param position The (character-indexed) position in the file where the check should
- * be performed.
- */
- function getDocCommentTemplateAtPosition(newLine, sourceFile, position) {
- var tokenAtPos = ts.getTokenAtPosition(sourceFile, position);
- var existingDocComment = ts.findAncestor(tokenAtPos, ts.isJSDoc);
- if (existingDocComment && (existingDocComment.comment !== undefined || ts.length(existingDocComment.tags))) {
- // Non-empty comment already exists.
- return undefined;
- }
- var tokenStart = tokenAtPos.getStart(sourceFile);
- // Don't provide a doc comment template based on a *previous* node. (But an existing empty jsdoc comment will likely start before `position`.)
- if (!existingDocComment && tokenStart < position) {
- return undefined;
- }
- var commentOwnerInfo = getCommentOwnerInfo(tokenAtPos);
- if (!commentOwnerInfo) {
- return undefined;
- }
- var commentOwner = commentOwnerInfo.commentOwner, parameters = commentOwnerInfo.parameters;
- if (commentOwner.getStart(sourceFile) < position) {
- return undefined;
- }
- if (!parameters || parameters.length === 0) {
- // if there are no parameters, just complete to a single line JSDoc comment
- var singleLineResult = "/** */";
- return { newText: singleLineResult, caretOffset: 3 };
- }
- var indentationStr = getIndentationStringAtPosition(sourceFile, position);
- // A doc comment consists of the following
- // * The opening comment line
- // * the first line (without a param) for the object's untagged info (this is also where the caret ends up)
- // * the '@param'-tagged lines
- // * TODO: other tags.
- // * the closing comment line
- // * if the caret was directly in front of the object, then we add an extra line and indentation.
- var preamble = "/**" + newLine + indentationStr + " * ";
- var result = preamble + newLine +
- parameterDocComments(parameters, ts.hasJSFileExtension(sourceFile.fileName), indentationStr, newLine) +
- indentationStr + " */" +
- (tokenStart === position ? newLine + indentationStr : "");
- return { newText: result, caretOffset: preamble.length };
- }
- JsDoc.getDocCommentTemplateAtPosition = getDocCommentTemplateAtPosition;
- function getIndentationStringAtPosition(sourceFile, position) {
- var text = sourceFile.text;
- var lineStart = ts.getLineStartPositionForPosition(position, sourceFile);
- var pos = lineStart;
- for (; pos <= position && ts.isWhiteSpaceSingleLine(text.charCodeAt(pos)); pos++)
- ;
- return text.slice(lineStart, pos);
- }
- function parameterDocComments(parameters, isJavaScriptFile, indentationStr, newLine) {
- return parameters.map(function (_a, i) {
- var name = _a.name, dotDotDotToken = _a.dotDotDotToken;
- var paramName = name.kind === 75 /* Identifier */ ? name.text : "param" + i;
- var type = isJavaScriptFile ? (dotDotDotToken ? "{...any} " : "{any} ") : "";
- return indentationStr + " * @param " + type + paramName + newLine;
- }).join("");
- }
- function getCommentOwnerInfo(tokenAtPos) {
- return ts.forEachAncestor(tokenAtPos, getCommentOwnerInfoWorker);
- }
- function getCommentOwnerInfoWorker(commentOwner) {
- switch (commentOwner.kind) {
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 161 /* MethodDeclaration */:
- case 162 /* Constructor */:
- case 160 /* MethodSignature */:
- var parameters = commentOwner.parameters;
- return { commentOwner: commentOwner, parameters: parameters };
- case 281 /* PropertyAssignment */:
- return getCommentOwnerInfoWorker(commentOwner.initializer);
- case 245 /* ClassDeclaration */:
- case 246 /* InterfaceDeclaration */:
- case 158 /* PropertySignature */:
- case 248 /* EnumDeclaration */:
- case 284 /* EnumMember */:
- case 247 /* TypeAliasDeclaration */:
- return { commentOwner: commentOwner };
- case 225 /* VariableStatement */: {
- var varStatement = commentOwner;
- var varDeclarations = varStatement.declarationList.declarations;
- var parameters_1 = varDeclarations.length === 1 && varDeclarations[0].initializer
- ? getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer)
- : undefined;
- return { commentOwner: commentOwner, parameters: parameters_1 };
- }
- case 290 /* SourceFile */:
- return "quit";
- case 249 /* ModuleDeclaration */:
- // If in walking up the tree, we hit a a nested namespace declaration,
- // then we must be somewhere within a dotted namespace name; however we don't
- // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'.
- return commentOwner.parent.kind === 249 /* ModuleDeclaration */ ? undefined : { commentOwner: commentOwner };
- case 226 /* ExpressionStatement */:
- return getCommentOwnerInfoWorker(commentOwner.expression);
- case 209 /* BinaryExpression */: {
- var be = commentOwner;
- if (ts.getAssignmentDeclarationKind(be) === 0 /* None */) {
- return "quit";
- }
- var parameters_2 = ts.isFunctionLike(be.right) ? be.right.parameters : ts.emptyArray;
- return { commentOwner: commentOwner, parameters: parameters_2 };
- }
- case 159 /* PropertyDeclaration */:
- var init = commentOwner.initializer;
- if (init && (ts.isFunctionExpression(init) || ts.isArrowFunction(init))) {
- return { commentOwner: commentOwner, parameters: init.parameters };
- }
- }
- }
- /**
- * Digs into an an initializer or RHS operand of an assignment operation
- * to get the parameters of an apt signature corresponding to a
- * function expression or a class expression.
- *
- * @param rightHandSide the expression which may contain an appropriate set of parameters
- * @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'.
- */
- function getParametersFromRightHandSideOfAssignment(rightHandSide) {
- while (rightHandSide.kind === 200 /* ParenthesizedExpression */) {
- rightHandSide = rightHandSide.expression;
- }
- switch (rightHandSide.kind) {
- case 201 /* FunctionExpression */:
- case 202 /* ArrowFunction */:
- return rightHandSide.parameters;
- case 214 /* ClassExpression */: {
- var ctr = ts.find(rightHandSide.members, ts.isConstructorDeclaration);
- return ctr ? ctr.parameters : ts.emptyArray;
- }
- }
- return ts.emptyArray;
- }
- })(JsDoc = ts.JsDoc || (ts.JsDoc = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var NavigateTo;
- (function (NavigateTo) {
- function getNavigateToItems(sourceFiles, checker, cancellationToken, searchValue, maxResultCount, excludeDtsFiles) {
- var patternMatcher = ts.createPatternMatcher(searchValue);
- if (!patternMatcher)
- return ts.emptyArray;
- var rawItems = [];
- var _loop_5 = function (sourceFile) {
- cancellationToken.throwIfCancellationRequested();
- if (excludeDtsFiles && sourceFile.isDeclarationFile) {
- return "continue";
- }
- sourceFile.getNamedDeclarations().forEach(function (declarations, name) {
- getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, sourceFile.fileName, rawItems);
- });
- };
- // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
- for (var _i = 0, sourceFiles_4 = sourceFiles; _i < sourceFiles_4.length; _i++) {
- var sourceFile = sourceFiles_4[_i];
- _loop_5(sourceFile);
- }
- rawItems.sort(compareNavigateToItems);
- return (maxResultCount === undefined ? rawItems : rawItems.slice(0, maxResultCount)).map(createNavigateToItem);
- }
- NavigateTo.getNavigateToItems = getNavigateToItems;
- function getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, fileName, rawItems) {
- // First do a quick check to see if the name of the declaration matches the
- // last portion of the (possibly) dotted name they're searching for.
- var match = patternMatcher.getMatchForLastSegmentOfPattern(name);
- if (!match) {
- return; // continue to next named declarations
- }
- for (var _i = 0, declarations_3 = declarations; _i < declarations_3.length; _i++) {
- var declaration = declarations_3[_i];
- if (!shouldKeepItem(declaration, checker))
- continue;
- if (patternMatcher.patternContainsDots) {
- // If the pattern has dots in it, then also see if the declaration container matches as well.
- var fullMatch = patternMatcher.getFullMatch(getContainers(declaration), name);
- if (fullMatch) {
- rawItems.push({ name: name, fileName: fileName, matchKind: fullMatch.kind, isCaseSensitive: fullMatch.isCaseSensitive, declaration: declaration });
- }
- }
- else {
- rawItems.push({ name: name, fileName: fileName, matchKind: match.kind, isCaseSensitive: match.isCaseSensitive, declaration: declaration });
- }
- }
- }
- function shouldKeepItem(declaration, checker) {
- switch (declaration.kind) {
- case 255 /* ImportClause */:
- case 258 /* ImportSpecifier */:
- case 253 /* ImportEqualsDeclaration */:
- var importer = checker.getSymbolAtLocation(declaration.name); // TODO: GH#18217
- var imported = checker.getAliasedSymbol(importer);
- return importer.escapedName !== imported.escapedName;
- default:
- return true;
- }
- }
- function tryAddSingleDeclarationName(declaration, containers) {
- var name = ts.getNameOfDeclaration(declaration);
- return !!name && (pushLiteral(name, containers) || name.kind === 154 /* ComputedPropertyName */ && tryAddComputedPropertyName(name.expression, containers));
- }
- // Only added the names of computed properties if they're simple dotted expressions, like:
- //
- // [X.Y.Z]() { }
- function tryAddComputedPropertyName(expression, containers) {
- return pushLiteral(expression, containers)
- || ts.isPropertyAccessExpression(expression) && (containers.push(expression.name.text), true) && tryAddComputedPropertyName(expression.expression, containers);
- }
- function pushLiteral(node, containers) {
- return ts.isPropertyNameLiteral(node) && (containers.push(ts.getTextOfIdentifierOrLiteral(node)), true);
- }
- function getContainers(declaration) {
- var containers = [];
- // First, if we started with a computed property name, then add all but the last
- // portion into the container array.
- var name = ts.getNameOfDeclaration(declaration);
- if (name && name.kind === 154 /* ComputedPropertyName */ && !tryAddComputedPropertyName(name.expression, containers)) {
- return ts.emptyArray;
- }
- // Don't include the last portion.
- containers.shift();
- // Now, walk up our containers, adding all their names to the container array.
- var container = ts.getContainerNode(declaration);
- while (container) {
- if (!tryAddSingleDeclarationName(container, containers)) {
- return ts.emptyArray;
- }
- container = ts.getContainerNode(container);
- }
- return containers.reverse();
- }
- function compareNavigateToItems(i1, i2) {
- // TODO(cyrusn): get the gamut of comparisons that VS already uses here.
- return ts.compareValues(i1.matchKind, i2.matchKind)
- || ts.compareStringsCaseSensitiveUI(i1.name, i2.name);
- }
- function createNavigateToItem(rawItem) {
- var declaration = rawItem.declaration;
- var container = ts.getContainerNode(declaration);
- var containerName = container && ts.getNameOfDeclaration(container);
- return {
- name: rawItem.name,
- kind: ts.getNodeKind(declaration),
- kindModifiers: ts.getNodeModifiers(declaration),
- matchKind: ts.PatternMatchKind[rawItem.matchKind],
- isCaseSensitive: rawItem.isCaseSensitive,
- fileName: rawItem.fileName,
- textSpan: ts.createTextSpanFromNode(declaration),
- // TODO(jfreeman): What should be the containerName when the container has a computed name?
- containerName: containerName ? containerName.text : "",
- containerKind: containerName ? ts.getNodeKind(container) : "" /* unknown */,
- };
- }
- })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var NavigationBar;
- (function (NavigationBar) {
- var _a;
- /**
- * Matches all whitespace characters in a string. Eg:
- *
- * "app.
- *
- * onactivated"
- *
- * matches because of the newline, whereas
- *
- * "app.onactivated"
- *
- * does not match.
- */
- var whiteSpaceRegex = /\s+/g;
- /**
- * Maximum amount of characters to return
- * The amount was chosen arbitrarily.
- */
- var maxLength = 150;
- // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`.
- var curCancellationToken;
- var curSourceFile;
- /**
- * For performance, we keep navigation bar parents on a stack rather than passing them through each recursion.
- * `parent` is the current parent and is *not* stored in parentsStack.
- * `startNode` sets a new parent and `endNode` returns to the previous parent.
- */
- var parentsStack = [];
- var parent;
- var trackedEs5ClassesStack = [];
- var trackedEs5Classes;
- // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance.
- var emptyChildItemArray = [];
- function getNavigationBarItems(sourceFile, cancellationToken) {
- curCancellationToken = cancellationToken;
- curSourceFile = sourceFile;
- try {
- return ts.map(primaryNavBarMenuItems(rootNavigationBarNode(sourceFile)), convertToPrimaryNavBarMenuItem);
- }
- finally {
- reset();
- }
- }
- NavigationBar.getNavigationBarItems = getNavigationBarItems;
- function getNavigationTree(sourceFile, cancellationToken) {
- curCancellationToken = cancellationToken;
- curSourceFile = sourceFile;
- try {
- return convertToTree(rootNavigationBarNode(sourceFile));
- }
- finally {
- reset();
- }
- }
- NavigationBar.getNavigationTree = getNavigationTree;
- function reset() {
- curSourceFile = undefined;
- curCancellationToken = undefined;
- parentsStack = [];
- parent = undefined;
- emptyChildItemArray = [];
- }
- function nodeText(node) {
- return cleanText(node.getText(curSourceFile));
- }
- function navigationBarNodeKind(n) {
- return n.node.kind;
- }
- function pushChild(parent, child) {
- if (parent.children) {
- parent.children.push(child);
- }
- else {
- parent.children = [child];
- }
- }
- function rootNavigationBarNode(sourceFile) {
- ts.Debug.assert(!parentsStack.length);
- var root = { node: sourceFile, name: undefined, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 };
- parent = root;
- for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- addChildrenRecursively(statement);
- }
- endNode();
- ts.Debug.assert(!parent && !parentsStack.length);
- return root;
- }
- function addLeafNode(node, name) {
- pushChild(parent, emptyNavigationBarNode(node, name));
- }
- function emptyNavigationBarNode(node, name) {
- return {
- node: node,
- name: name || (ts.isDeclaration(node) || ts.isExpression(node) ? ts.getNameOfDeclaration(node) : undefined),
- additionalNodes: undefined,
- parent: parent,
- children: undefined,
- indent: parent.indent + 1
- };
- }
- function addTrackedEs5Class(name) {
- if (!trackedEs5Classes) {
- trackedEs5Classes = ts.createMap();
- }
- trackedEs5Classes.set(name, true);
- }
- function endNestedNodes(depth) {
- for (var i = 0; i < depth; i++)
- endNode();
- }
- function startNestedNodes(targetNode, entityName) {
- var names = [];
- while (!ts.isPropertyNameLiteral(entityName)) {
- var name = ts.getNameOrArgument(entityName);
- var nameText = ts.getElementOrPropertyAccessName(entityName);
- entityName = entityName.expression;
- if (nameText === "prototype" || ts.isPrivateIdentifier(name))
- continue;
- names.push(name);
- }
- names.push(entityName);
- for (var i = names.length - 1; i > 0; i--) {
- var name = names[i];
- startNode(targetNode, name);
- }
- return [names.length - 1, names[0]];
- }
- /**
- * Add a new level of NavigationBarNodes.
- * This pushes to the stack, so you must call `endNode` when you are done adding to this node.
- */
- function startNode(node, name) {
- var navNode = emptyNavigationBarNode(node, name);
- pushChild(parent, navNode);
- // Save the old parent
- parentsStack.push(parent);
- trackedEs5ClassesStack.push(trackedEs5Classes);
- parent = navNode;
- }
- /** Call after calling `startNode` and adding children to it. */
- function endNode() {
- if (parent.children) {
- mergeChildren(parent.children, parent);
- sortChildren(parent.children);
- }
- parent = parentsStack.pop();
- trackedEs5Classes = trackedEs5ClassesStack.pop();
- }
- function addNodeWithRecursiveChild(node, child, name) {
- startNode(node, name);
- addChildrenRecursively(child);
- endNode();
- }
- /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */
- function addChildrenRecursively(node) {
- var _a;
- curCancellationToken.throwIfCancellationRequested();
- if (!node || ts.isToken(node)) {
- return;
- }
- switch (node.kind) {
- case 162 /* Constructor */:
- // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it.
- var ctr = node;
- addNodeWithRecursiveChild(ctr, ctr.body);
- // Parameter properties are children of the class, not the constructor.
- for (var _i = 0, _b = ctr.parameters; _i < _b.length; _i++) {
- var param = _b[_i];
- if (ts.isParameterPropertyDeclaration(param, ctr)) {
- addLeafNode(param);
- }
- }
- break;
- case 161 /* MethodDeclaration */:
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- case 160 /* MethodSignature */:
- if (!ts.hasDynamicName(node)) {
- addNodeWithRecursiveChild(node, node.body);
- }
- break;
- case 159 /* PropertyDeclaration */:
- case 158 /* PropertySignature */:
- if (!ts.hasDynamicName(node)) {
- addLeafNode(node);
- }
- break;
- case 255 /* ImportClause */:
- var importClause = node;
- // Handle default import case e.g.:
- // import d from "mod";
- if (importClause.name) {
- addLeafNode(importClause.name);
- }
- // Handle named bindings in imports e.g.:
- // import * as NS from "mod";
- // import {a, b as B} from "mod";
- var namedBindings = importClause.namedBindings;
- if (namedBindings) {
- if (namedBindings.kind === 256 /* NamespaceImport */) {
- addLeafNode(namedBindings);
- }
- else {
- for (var _c = 0, _d = namedBindings.elements; _c < _d.length; _c++) {
- var element = _d[_c];
- addLeafNode(element);
- }
- }
- }
- break;
- case 282 /* ShorthandPropertyAssignment */:
- addNodeWithRecursiveChild(node, node.name);
- break;
- case 283 /* SpreadAssignment */:
- var expression = node.expression;
- // Use the expression as the name of the SpreadAssignment, otherwise show as .
- ts.isIdentifier(expression) ? addLeafNode(node, expression) : addLeafNode(node);
- break;
- case 191 /* BindingElement */:
- case 281 /* PropertyAssignment */:
- case 242 /* VariableDeclaration */:
- var _e = node, name = _e.name, initializer = _e.initializer;
- if (ts.isBindingPattern(name)) {
- addChildrenRecursively(name);
- }
- else if (initializer && isFunctionOrClassExpression(initializer)) {
- // Add a node for the VariableDeclaration, but not for the initializer.
- startNode(node);
- ts.forEachChild(initializer, addChildrenRecursively);
- endNode();
- }
- else {
- addNodeWithRecursiveChild(node, initializer);
- }
- break;
- case 244 /* FunctionDeclaration */:
- var nameNode = node.name;
- // If we see a function declaration track as a possible ES5 class
- if (nameNode && ts.isIdentifier(nameNode)) {
- addTrackedEs5Class(nameNode.text);
- }
- addNodeWithRecursiveChild(node, node.body);
- break;
- case 202 /* ArrowFunction */:
- case 201 /* FunctionExpression */:
- addNodeWithRecursiveChild(node, node.body);
- break;
- case 248 /* EnumDeclaration */:
- startNode(node);
- for (var _f = 0, _g = node.members; _f < _g.length; _f++) {
- var member = _g[_f];
- if (!isComputedProperty(member)) {
- addLeafNode(member);
- }
- }
- endNode();
- break;
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 246 /* InterfaceDeclaration */:
- startNode(node);
- for (var _h = 0, _j = node.members; _h < _j.length; _h++) {
- var member = _j[_h];
- addChildrenRecursively(member);
- }
- endNode();
- break;
- case 249 /* ModuleDeclaration */:
- addNodeWithRecursiveChild(node, getInteriorModule(node).body);
- break;
- case 259 /* ExportAssignment */:
- case 263 /* ExportSpecifier */:
- case 253 /* ImportEqualsDeclaration */:
- case 167 /* IndexSignature */:
- case 165 /* CallSignature */:
- case 166 /* ConstructSignature */:
- case 247 /* TypeAliasDeclaration */:
- addLeafNode(node);
- break;
- case 196 /* CallExpression */:
- case 209 /* BinaryExpression */: {
- var special = ts.getAssignmentDeclarationKind(node);
- switch (special) {
- case 1 /* ExportsProperty */:
- case 2 /* ModuleExports */:
- addNodeWithRecursiveChild(node, node.right);
- return;
- case 6 /* Prototype */:
- case 3 /* PrototypeProperty */: {
- var binaryExpression = node;
- var assignmentTarget = binaryExpression.left;
- var prototypeAccess = special === 3 /* PrototypeProperty */ ?
- assignmentTarget.expression :
- assignmentTarget;
- var depth = 0;
- var className = void 0;
- // If we see a prototype assignment, start tracking the target as a class
- // This is only done for simple classes not nested assignments.
- if (ts.isIdentifier(prototypeAccess.expression)) {
- addTrackedEs5Class(prototypeAccess.expression.text);
- className = prototypeAccess.expression;
- }
- else {
- _a = startNestedNodes(binaryExpression, prototypeAccess.expression), depth = _a[0], className = _a[1];
- }
- if (special === 6 /* Prototype */) {
- if (ts.isObjectLiteralExpression(binaryExpression.right)) {
- if (binaryExpression.right.properties.length > 0) {
- startNode(binaryExpression, className);
- ts.forEachChild(binaryExpression.right, addChildrenRecursively);
- endNode();
- }
- }
- }
- else if (ts.isFunctionExpression(binaryExpression.right) || ts.isArrowFunction(binaryExpression.right)) {
- addNodeWithRecursiveChild(node, binaryExpression.right, className);
- }
- else {
- startNode(binaryExpression, className);
- addNodeWithRecursiveChild(node, binaryExpression.right, assignmentTarget.name);
- endNode();
- }
- endNestedNodes(depth);
- return;
- }
- case 7 /* ObjectDefinePropertyValue */:
- case 9 /* ObjectDefinePrototypeProperty */: {
- var defineCall = node;
- var className = special === 7 /* ObjectDefinePropertyValue */ ?
- defineCall.arguments[0] :
- defineCall.arguments[0].expression;
- var memberName = defineCall.arguments[1];
- var _k = startNestedNodes(node, className), depth = _k[0], classNameIdentifier = _k[1];
- startNode(node, classNameIdentifier);
- startNode(node, ts.setTextRange(ts.createIdentifier(memberName.text), memberName));
- addChildrenRecursively(node.arguments[2]);
- endNode();
- endNode();
- endNestedNodes(depth);
- return;
- }
- case 5 /* Property */: {
- var binaryExpression = node;
- var assignmentTarget = binaryExpression.left;
- var targetFunction = assignmentTarget.expression;
- if (ts.isIdentifier(targetFunction) && ts.getElementOrPropertyAccessName(assignmentTarget) !== "prototype" &&
- trackedEs5Classes && trackedEs5Classes.has(targetFunction.text)) {
- if (ts.isFunctionExpression(binaryExpression.right) || ts.isArrowFunction(binaryExpression.right)) {
- addNodeWithRecursiveChild(node, binaryExpression.right, targetFunction);
- }
- else if (ts.isBindableStaticAccessExpression(assignmentTarget)) {
- startNode(binaryExpression, targetFunction);
- addNodeWithRecursiveChild(binaryExpression.left, binaryExpression.right, ts.getNameOrArgument(assignmentTarget));
- endNode();
- }
- return;
- }
- break;
- }
- case 4 /* ThisProperty */:
- case 0 /* None */:
- case 8 /* ObjectDefinePropertyExports */:
- break;
- default:
- ts.Debug.assertNever(special);
- }
- }
- // falls through
- default:
- if (ts.hasJSDocNodes(node)) {
- ts.forEach(node.jsDoc, function (jsDoc) {
- ts.forEach(jsDoc.tags, function (tag) {
- if (ts.isJSDocTypeAlias(tag)) {
- addLeafNode(tag);
- }
- });
- });
- }
- ts.forEachChild(node, addChildrenRecursively);
- }
- }
- /** Merge declarations of the same kind. */
- function mergeChildren(children, node) {
- var nameToItems = ts.createMap();
- ts.filterMutate(children, function (child, index) {
- var declName = child.name || ts.getNameOfDeclaration(child.node);
- var name = declName && nodeText(declName);
- if (!name) {
- // Anonymous items are never merged.
- return true;
- }
- var itemsWithSameName = nameToItems.get(name);
- if (!itemsWithSameName) {
- nameToItems.set(name, child);
- return true;
- }
- if (itemsWithSameName instanceof Array) {
- for (var _i = 0, itemsWithSameName_1 = itemsWithSameName; _i < itemsWithSameName_1.length; _i++) {
- var itemWithSameName = itemsWithSameName_1[_i];
- if (tryMerge(itemWithSameName, child, index, node)) {
- return false;
- }
- }
- itemsWithSameName.push(child);
- return true;
- }
- else {
- var itemWithSameName = itemsWithSameName;
- if (tryMerge(itemWithSameName, child, index, node)) {
- return false;
- }
- nameToItems.set(name, [itemWithSameName, child]);
- return true;
- }
- });
- }
- var isEs5ClassMember = (_a = {},
- _a[5 /* Property */] = true,
- _a[3 /* PrototypeProperty */] = true,
- _a[7 /* ObjectDefinePropertyValue */] = true,
- _a[9 /* ObjectDefinePrototypeProperty */] = true,
- _a[0 /* None */] = false,
- _a[1 /* ExportsProperty */] = false,
- _a[2 /* ModuleExports */] = false,
- _a[8 /* ObjectDefinePropertyExports */] = false,
- _a[6 /* Prototype */] = true,
- _a[4 /* ThisProperty */] = false,
- _a);
- function tryMergeEs5Class(a, b, bIndex, parent) {
- function isPossibleConstructor(node) {
- return ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isVariableDeclaration(node);
- }
- var bAssignmentDeclarationKind = ts.isBinaryExpression(b.node) || ts.isCallExpression(b.node) ?
- ts.getAssignmentDeclarationKind(b.node) :
- 0 /* None */;
- var aAssignmentDeclarationKind = ts.isBinaryExpression(a.node) || ts.isCallExpression(a.node) ?
- ts.getAssignmentDeclarationKind(a.node) :
- 0 /* None */;
- // We treat this as an es5 class and merge the nodes in in one of several cases
- if ((isEs5ClassMember[bAssignmentDeclarationKind] && isEs5ClassMember[aAssignmentDeclarationKind]) // merge two class elements
- || (isPossibleConstructor(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // ctor function & member
- || (isPossibleConstructor(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & ctor function
- || (ts.isClassDeclaration(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // class (generated) & member
- || (ts.isClassDeclaration(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & class (generated)
- || (ts.isClassDeclaration(a.node) && isPossibleConstructor(b.node)) // class (generated) & ctor
- || (ts.isClassDeclaration(b.node) && isPossibleConstructor(a.node)) // ctor & class (generated)
- ) {
- var lastANode = a.additionalNodes && ts.lastOrUndefined(a.additionalNodes) || a.node;
- if ((!ts.isClassDeclaration(a.node) && !ts.isClassDeclaration(b.node)) // If neither outline node is a class
- || isPossibleConstructor(a.node) || isPossibleConstructor(b.node) // If either function is a constructor function
- ) {
- var ctorFunction = isPossibleConstructor(a.node) ? a.node :
- isPossibleConstructor(b.node) ? b.node :
- undefined;
- if (ctorFunction !== undefined) {
- var ctorNode = ts.setTextRange(ts.createConstructor(/* decorators */ undefined, /* modifiers */ undefined, [], /* body */ undefined), ctorFunction);
- var ctor = emptyNavigationBarNode(ctorNode);
- ctor.indent = a.indent + 1;
- ctor.children = a.node === ctorFunction ? a.children : b.children;
- a.children = a.node === ctorFunction ? ts.concatenate([ctor], b.children || [b]) : ts.concatenate(a.children || [a], [ctor]);
- }
- else {
- if (a.children || b.children) {
- a.children = ts.concatenate(a.children || [a], b.children || [b]);
- if (a.children) {
- mergeChildren(a.children, a);
- sortChildren(a.children);
- }
- }
- }
- lastANode = a.node = ts.setTextRange(ts.createClassDeclaration(
- /* decorators */ undefined,
- /* modifiers */ undefined, a.name || ts.createIdentifier("__class__"),
- /* typeParameters */ undefined,
- /* heritageClauses */ undefined, []), a.node);
- }
- else {
- a.children = ts.concatenate(a.children, b.children);
- if (a.children) {
- mergeChildren(a.children, a);
- }
- }
- var bNode = b.node;
- // We merge if the outline node previous to b (bIndex - 1) is already part of the current class
- // We do this so that statements between class members that do not generate outline nodes do not split up the class outline:
- // Ex This should produce one outline node C:
- // function C() {}; a = 1; C.prototype.m = function () {}
- // Ex This will produce 3 outline nodes: C, a, C
- // function C() {}; let a = 1; C.prototype.m = function () {}
- if (parent.children[bIndex - 1].node.end === lastANode.end) {
- ts.setTextRange(lastANode, { pos: lastANode.pos, end: bNode.end });
- }
- else {
- if (!a.additionalNodes)
- a.additionalNodes = [];
- a.additionalNodes.push(ts.setTextRange(ts.createClassDeclaration(
- /* decorators */ undefined,
- /* modifiers */ undefined, a.name || ts.createIdentifier("__class__"),
- /* typeParameters */ undefined,
- /* heritageClauses */ undefined, []), b.node));
- }
- return true;
- }
- return bAssignmentDeclarationKind === 0 /* None */ ? false : true;
- }
- function tryMerge(a, b, bIndex, parent) {
- // const v = false as boolean;
- if (tryMergeEs5Class(a, b, bIndex, parent)) {
- return true;
- }
- if (shouldReallyMerge(a.node, b.node, parent)) {
- merge(a, b);
- return true;
- }
- return false;
- }
- /** a and b have the same name, but they may not be mergeable. */
- function shouldReallyMerge(a, b, parent) {
- if (a.kind !== b.kind || a.parent !== b.parent && !(isOwnChild(a, parent) && isOwnChild(b, parent))) {
- return false;
- }
- switch (a.kind) {
- case 159 /* PropertyDeclaration */:
- case 161 /* MethodDeclaration */:
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- return ts.hasModifier(a, 32 /* Static */) === ts.hasModifier(b, 32 /* Static */);
- case 249 /* ModuleDeclaration */:
- return areSameModule(a, b);
- default:
- return true;
- }
- }
- // We want to merge own children like `I` in in `module A { interface I {} } module A { interface I {} }`
- // We don't want to merge unrelated children like `m` in `const o = { a: { m() {} }, b: { m() {} } };`
- function isOwnChild(n, parent) {
- var par = ts.isModuleBlock(n.parent) ? n.parent.parent : n.parent;
- return par === parent.node || ts.contains(parent.additionalNodes, par);
- }
- // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes.
- // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'!
- function areSameModule(a, b) {
- // TODO: GH#18217
- return a.body.kind === b.body.kind && (a.body.kind !== 249 /* ModuleDeclaration */ || areSameModule(a.body, b.body));
- }
- /** Merge source into target. Source should be thrown away after this is called. */
- function merge(target, source) {
- var _a;
- target.additionalNodes = target.additionalNodes || [];
- target.additionalNodes.push(source.node);
- if (source.additionalNodes) {
- (_a = target.additionalNodes).push.apply(_a, source.additionalNodes);
- }
- target.children = ts.concatenate(target.children, source.children);
- if (target.children) {
- mergeChildren(target.children, target);
- sortChildren(target.children);
- }
- }
- /** Recursively ensure that each NavNode's children are in sorted order. */
- function sortChildren(children) {
- children.sort(compareChildren);
- }
- function compareChildren(child1, child2) {
- return ts.compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node)) // TODO: GH#18217
- || ts.compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2));
- }
- /**
- * This differs from getItemName because this is just used for sorting.
- * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like.
- * So `new()` can still come before an `aardvark` method.
- */
- function tryGetName(node) {
- if (node.kind === 249 /* ModuleDeclaration */) {
- return getModuleName(node);
- }
- var declName = ts.getNameOfDeclaration(node);
- if (declName && ts.isPropertyName(declName)) {
- var propertyName = ts.getPropertyNameForPropertyNameNode(declName);
- return propertyName && ts.unescapeLeadingUnderscores(propertyName);
- }
- switch (node.kind) {
- case 201 /* FunctionExpression */:
- case 202 /* ArrowFunction */:
- case 214 /* ClassExpression */:
- return getFunctionOrClassName(node);
- default:
- return undefined;
- }
- }
- function getItemName(node, name) {
- if (node.kind === 249 /* ModuleDeclaration */) {
- return cleanText(getModuleName(node));
- }
- if (name) {
- var text = ts.isIdentifier(name) ? name.text
- : ts.isElementAccessExpression(name) ? "[" + nodeText(name.argumentExpression) + "]"
- : nodeText(name);
- if (text.length > 0) {
- return cleanText(text);
- }
- }
- switch (node.kind) {
- case 290 /* SourceFile */:
- var sourceFile = node;
- return ts.isExternalModule(sourceFile)
- ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))) + "\""
- : "";
- case 259 /* ExportAssignment */:
- return ts.isExportAssignment(node) && node.isExportEquals ? "export=" /* ExportEquals */ : "default" /* Default */;
- case 202 /* ArrowFunction */:
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- if (ts.getModifierFlags(node) & 512 /* Default */) {
- return "default";
- }
- // We may get a string with newlines or other whitespace in the case of an object dereference
- // (eg: "app\n.onactivated"), so we should remove the whitespace for readabiltiy in the
- // navigation bar.
- return getFunctionOrClassName(node);
- case 162 /* Constructor */:
- return "constructor";
- case 166 /* ConstructSignature */:
- return "new()";
- case 165 /* CallSignature */:
- return "()";
- case 167 /* IndexSignature */:
- return "[]";
- default:
- return "";
- }
- }
- /** Flattens the NavNode tree to a list of items to appear in the primary navbar menu. */
- function primaryNavBarMenuItems(root) {
- // The primary (middle) navbar menu displays the general code navigation hierarchy, similar to the navtree.
- // The secondary (right) navbar menu displays the child items of whichever primary item is selected.
- // Some less interesting items without their own child navigation items (e.g. a local variable declaration) only show up in the secondary menu.
- var primaryNavBarMenuItems = [];
- function recur(item) {
- if (shouldAppearInPrimaryNavBarMenu(item)) {
- primaryNavBarMenuItems.push(item);
- if (item.children) {
- for (var _i = 0, _a = item.children; _i < _a.length; _i++) {
- var child = _a[_i];
- recur(child);
- }
- }
- }
- }
- recur(root);
- return primaryNavBarMenuItems;
- /** Determines if a node should appear in the primary navbar menu. */
- function shouldAppearInPrimaryNavBarMenu(item) {
- // Items with children should always appear in the primary navbar menu.
- if (item.children) {
- return true;
- }
- // Some nodes are otherwise important enough to always include in the primary navigation menu.
- switch (navigationBarNodeKind(item)) {
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 248 /* EnumDeclaration */:
- case 246 /* InterfaceDeclaration */:
- case 249 /* ModuleDeclaration */:
- case 290 /* SourceFile */:
- case 247 /* TypeAliasDeclaration */:
- case 322 /* JSDocTypedefTag */:
- case 315 /* JSDocCallbackTag */:
- return true;
- case 202 /* ArrowFunction */:
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- return isTopLevelFunctionDeclaration(item);
- default:
- return false;
- }
- function isTopLevelFunctionDeclaration(item) {
- if (!item.node.body) {
- return false;
- }
- switch (navigationBarNodeKind(item.parent)) {
- case 250 /* ModuleBlock */:
- case 290 /* SourceFile */:
- case 161 /* MethodDeclaration */:
- case 162 /* Constructor */:
- return true;
- default:
- return false;
- }
- }
- }
- }
- function convertToTree(n) {
- return {
- text: getItemName(n.node, n.name),
- kind: ts.getNodeKind(n.node),
- kindModifiers: getModifiers(n.node),
- spans: getSpans(n),
- nameSpan: n.name && getNodeSpan(n.name),
- childItems: ts.map(n.children, convertToTree)
- };
- }
- function convertToPrimaryNavBarMenuItem(n) {
- return {
- text: getItemName(n.node, n.name),
- kind: ts.getNodeKind(n.node),
- kindModifiers: getModifiers(n.node),
- spans: getSpans(n),
- childItems: ts.map(n.children, convertToSecondaryNavBarMenuItem) || emptyChildItemArray,
- indent: n.indent,
- bolded: false,
- grayed: false
- };
- function convertToSecondaryNavBarMenuItem(n) {
- return {
- text: getItemName(n.node, n.name),
- kind: ts.getNodeKind(n.node),
- kindModifiers: ts.getNodeModifiers(n.node),
- spans: getSpans(n),
- childItems: emptyChildItemArray,
- indent: 0,
- bolded: false,
- grayed: false
- };
- }
- }
- function getSpans(n) {
- var spans = [getNodeSpan(n.node)];
- if (n.additionalNodes) {
- for (var _i = 0, _a = n.additionalNodes; _i < _a.length; _i++) {
- var node = _a[_i];
- spans.push(getNodeSpan(node));
- }
- }
- return spans;
- }
- function getModuleName(moduleDeclaration) {
- // We want to maintain quotation marks.
- if (ts.isAmbientModule(moduleDeclaration)) {
- return ts.getTextOfNode(moduleDeclaration.name);
- }
- // Otherwise, we need to aggregate each identifier to build up the qualified name.
- var result = [];
- result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name));
- while (moduleDeclaration.body && moduleDeclaration.body.kind === 249 /* ModuleDeclaration */) {
- moduleDeclaration = moduleDeclaration.body;
- result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name));
- }
- return result.join(".");
- }
- /**
- * For 'module A.B.C', we want to get the node for 'C'.
- * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again.
- */
- function getInteriorModule(decl) {
- return decl.body && ts.isModuleDeclaration(decl.body) ? getInteriorModule(decl.body) : decl;
- }
- function isComputedProperty(member) {
- return !member.name || member.name.kind === 154 /* ComputedPropertyName */;
- }
- function getNodeSpan(node) {
- return node.kind === 290 /* SourceFile */ ? ts.createTextSpanFromRange(node) : ts.createTextSpanFromNode(node, curSourceFile);
- }
- function getModifiers(node) {
- if (node.parent && node.parent.kind === 242 /* VariableDeclaration */) {
- node = node.parent;
- }
- return ts.getNodeModifiers(node);
- }
- function getFunctionOrClassName(node) {
- var parent = node.parent;
- if (node.name && ts.getFullWidth(node.name) > 0) {
- return cleanText(ts.declarationNameToString(node.name));
- }
- // See if it is a var initializer. If so, use the var name.
- else if (ts.isVariableDeclaration(parent)) {
- return cleanText(ts.declarationNameToString(parent.name));
- }
- // See if it is of the form " = function(){...}". If so, use the text from the left-hand side.
- else if (ts.isBinaryExpression(parent) && parent.operatorToken.kind === 62 /* EqualsToken */) {
- return nodeText(parent.left).replace(whiteSpaceRegex, "");
- }
- // See if it is a property assignment, and if so use the property name
- else if (ts.isPropertyAssignment(parent)) {
- return nodeText(parent.name);
- }
- // Default exports are named "default"
- else if (ts.getModifierFlags(node) & 512 /* Default */) {
- return "default";
- }
- else if (ts.isClassLike(node)) {
- return "";
- }
- else if (ts.isCallExpression(parent)) {
- var name = getCalledExpressionName(parent.expression);
- if (name !== undefined) {
- name = cleanText(name);
- if (name.length > maxLength) {
- return name + " callback";
- }
- var args = cleanText(ts.mapDefined(parent.arguments, function (a) { return ts.isStringLiteralLike(a) ? a.getText(curSourceFile) : undefined; }).join(", "));
- return name + "(" + args + ") callback";
- }
- }
- return "";
- }
- // See also 'tryGetPropertyAccessOrIdentifierToString'
- function getCalledExpressionName(expr) {
- if (ts.isIdentifier(expr)) {
- return expr.text;
- }
- else if (ts.isPropertyAccessExpression(expr)) {
- var left = getCalledExpressionName(expr.expression);
- var right = expr.name.text;
- return left === undefined ? right : left + "." + right;
- }
- else {
- return undefined;
- }
- }
- function isFunctionOrClassExpression(node) {
- switch (node.kind) {
- case 202 /* ArrowFunction */:
- case 201 /* FunctionExpression */:
- case 214 /* ClassExpression */:
- return true;
- default:
- return false;
- }
- }
- function cleanText(text) {
- // Truncate to maximum amount of characters as we don't want to do a big replace operation.
- text = text.length > maxLength ? text.substring(0, maxLength) + "..." : text;
- // Replaces ECMAScript line terminators and removes the trailing `\` from each line:
- // \n - Line Feed
- // \r - Carriage Return
- // \u2028 - Line separator
- // \u2029 - Paragraph separator
- return text.replace(/\\?(\r?\n|\r|\u2028|\u2029)/g, "");
- }
- })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var OrganizeImports;
- (function (OrganizeImports) {
- /**
- * Organize imports by:
- * 1) Removing unused imports
- * 2) Coalescing imports from the same module
- * 3) Sorting imports
- */
- function organizeImports(sourceFile, formatContext, host, program, preferences) {
- var changeTracker = ts.textChanges.ChangeTracker.fromContext({ host: host, formatContext: formatContext, preferences: preferences });
- var coalesceAndOrganizeImports = function (importGroup) { return coalesceImports(removeUnusedImports(importGroup, sourceFile, program)); };
- // All of the old ImportDeclarations in the file, in syntactic order.
- var topLevelImportDecls = sourceFile.statements.filter(ts.isImportDeclaration);
- organizeImportsWorker(topLevelImportDecls, coalesceAndOrganizeImports);
- // All of the old ExportDeclarations in the file, in syntactic order.
- var topLevelExportDecls = sourceFile.statements.filter(ts.isExportDeclaration);
- organizeImportsWorker(topLevelExportDecls, coalesceExports);
- for (var _i = 0, _a = sourceFile.statements.filter(ts.isAmbientModule); _i < _a.length; _i++) {
- var ambientModule = _a[_i];
- if (!ambientModule.body) {
- continue;
- }
- var ambientModuleImportDecls = ambientModule.body.statements.filter(ts.isImportDeclaration);
- organizeImportsWorker(ambientModuleImportDecls, coalesceAndOrganizeImports);
- var ambientModuleExportDecls = ambientModule.body.statements.filter(ts.isExportDeclaration);
- organizeImportsWorker(ambientModuleExportDecls, coalesceExports);
- }
- return changeTracker.getChanges();
- function organizeImportsWorker(oldImportDecls, coalesce) {
- if (ts.length(oldImportDecls) === 0) {
- return;
- }
- // Special case: normally, we'd expect leading and trailing trivia to follow each import
- // around as it's sorted. However, we do not want this to happen for leading trivia
- // on the first import because it is probably the header comment for the file.
- // Consider: we could do a more careful check that this trivia is actually a header,
- // but the consequences of being wrong are very minor.
- ts.suppressLeadingTrivia(oldImportDecls[0]);
- var oldImportGroups = ts.group(oldImportDecls, function (importDecl) { return getExternalModuleName(importDecl.moduleSpecifier); });
- var sortedImportGroups = ts.stableSort(oldImportGroups, function (group1, group2) { return compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier); });
- var newImportDecls = ts.flatMap(sortedImportGroups, function (importGroup) {
- return getExternalModuleName(importGroup[0].moduleSpecifier)
- ? coalesce(importGroup)
- : importGroup;
- });
- // Delete or replace the first import.
- if (newImportDecls.length === 0) {
- changeTracker.delete(sourceFile, oldImportDecls[0]);
- }
- else {
- // Note: Delete the surrounding trivia because it will have been retained in newImportDecls.
- changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, {
- leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude,
- trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include,
- suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options),
- });
- }
- // Delete any subsequent imports.
- for (var i = 1; i < oldImportDecls.length; i++) {
- changeTracker.deleteNode(sourceFile, oldImportDecls[i]);
- }
- }
- }
- OrganizeImports.organizeImports = organizeImports;
- function removeUnusedImports(oldImports, sourceFile, program) {
- var typeChecker = program.getTypeChecker();
- var jsxNamespace = typeChecker.getJsxNamespace(sourceFile);
- var jsxElementsPresent = !!(sourceFile.transformFlags & 2 /* ContainsJsx */);
- var usedImports = [];
- for (var _i = 0, oldImports_1 = oldImports; _i < oldImports_1.length; _i++) {
- var importDecl = oldImports_1[_i];
- var importClause = importDecl.importClause, moduleSpecifier = importDecl.moduleSpecifier;
- if (!importClause) {
- // Imports without import clauses are assumed to be included for their side effects and are not removed.
- usedImports.push(importDecl);
- continue;
- }
- var name = importClause.name, namedBindings = importClause.namedBindings;
- // Default import
- if (name && !isDeclarationUsed(name)) {
- name = undefined;
- }
- if (namedBindings) {
- if (ts.isNamespaceImport(namedBindings)) {
- // Namespace import
- if (!isDeclarationUsed(namedBindings.name)) {
- namedBindings = undefined;
- }
- }
- else {
- // List of named imports
- var newElements = namedBindings.elements.filter(function (e) { return isDeclarationUsed(e.name); });
- if (newElements.length < namedBindings.elements.length) {
- namedBindings = newElements.length
- ? ts.updateNamedImports(namedBindings, newElements)
- : undefined;
- }
- }
- }
- if (name || namedBindings) {
- usedImports.push(updateImportDeclarationAndClause(importDecl, name, namedBindings));
- }
- // If a module is imported to be augmented, it’s used
- else if (hasModuleDeclarationMatchingSpecifier(sourceFile, moduleSpecifier)) {
- // If we’re in a declaration file, it’s safe to remove the import clause from it
- if (sourceFile.isDeclarationFile) {
- usedImports.push(ts.createImportDeclaration(importDecl.decorators, importDecl.modifiers,
- /*importClause*/ undefined, moduleSpecifier));
- }
- // If we’re not in a declaration file, we can’t remove the import clause even though
- // the imported symbols are unused, because removing them makes it look like the import
- // declaration has side effects, which will cause it to be preserved in the JS emit.
- else {
- usedImports.push(importDecl);
- }
- }
- }
- return usedImports;
- function isDeclarationUsed(identifier) {
- // The JSX factory symbol is always used if JSX elements are present - even if they are not allowed.
- return jsxElementsPresent && (identifier.text === jsxNamespace) || ts.FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile);
- }
- }
- function hasModuleDeclarationMatchingSpecifier(sourceFile, moduleSpecifier) {
- var moduleSpecifierText = ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text;
- return ts.isString(moduleSpecifierText) && ts.some(sourceFile.moduleAugmentations, function (moduleName) {
- return ts.isStringLiteral(moduleName)
- && moduleName.text === moduleSpecifierText;
- });
- }
- function getExternalModuleName(specifier) {
- return specifier !== undefined && ts.isStringLiteralLike(specifier)
- ? specifier.text
- : undefined;
- }
- // Internal for testing
- /**
- * @param importGroup a list of ImportDeclarations, all with the same module name.
- */
- function coalesceImports(importGroup) {
- var _a;
- if (importGroup.length === 0) {
- return importGroup;
- }
- var _b = getCategorizedImports(importGroup), importWithoutClause = _b.importWithoutClause, typeOnlyImports = _b.typeOnlyImports, regularImports = _b.regularImports;
- var coalescedImports = [];
- if (importWithoutClause) {
- coalescedImports.push(importWithoutClause);
- }
- for (var _i = 0, _c = [regularImports, typeOnlyImports]; _i < _c.length; _i++) {
- var group_2 = _c[_i];
- var isTypeOnly = group_2 === typeOnlyImports;
- var defaultImports = group_2.defaultImports, namespaceImports = group_2.namespaceImports, namedImports = group_2.namedImports;
- // Normally, we don't combine default and namespace imports, but it would be silly to
- // produce two import declarations in this special case.
- if (!isTypeOnly && defaultImports.length === 1 && namespaceImports.length === 1 && namedImports.length === 0) {
- // Add the namespace import to the existing default ImportDeclaration.
- var defaultImport = defaultImports[0];
- coalescedImports.push(updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings)); // TODO: GH#18217
- continue;
- }
- var sortedNamespaceImports = ts.stableSort(namespaceImports, function (i1, i2) {
- return compareIdentifiers(i1.importClause.namedBindings.name, i2.importClause.namedBindings.name);
- }); // TODO: GH#18217
- for (var _d = 0, sortedNamespaceImports_1 = sortedNamespaceImports; _d < sortedNamespaceImports_1.length; _d++) {
- var namespaceImport = sortedNamespaceImports_1[_d];
- // Drop the name, if any
- coalescedImports.push(updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause.namedBindings)); // TODO: GH#18217
- }
- if (defaultImports.length === 0 && namedImports.length === 0) {
- continue;
- }
- var newDefaultImport = void 0;
- var newImportSpecifiers = [];
- if (defaultImports.length === 1) {
- newDefaultImport = defaultImports[0].importClause.name;
- }
- else {
- for (var _e = 0, defaultImports_1 = defaultImports; _e < defaultImports_1.length; _e++) {
- var defaultImport = defaultImports_1[_e];
- newImportSpecifiers.push(ts.createImportSpecifier(ts.createIdentifier("default"), defaultImport.importClause.name)); // TODO: GH#18217
- }
- }
- newImportSpecifiers.push.apply(newImportSpecifiers, ts.flatMap(namedImports, function (i) { return i.importClause.namedBindings.elements; })); // TODO: GH#18217
- var sortedImportSpecifiers = sortSpecifiers(newImportSpecifiers);
- var importDecl = defaultImports.length > 0
- ? defaultImports[0]
- : namedImports[0];
- var newNamedImports = sortedImportSpecifiers.length === 0
- ? newDefaultImport
- ? undefined
- : ts.createNamedImports(ts.emptyArray)
- : namedImports.length === 0
- ? ts.createNamedImports(sortedImportSpecifiers)
- : ts.updateNamedImports(namedImports[0].importClause.namedBindings, sortedImportSpecifiers); // TODO: GH#18217
- // Type-only imports are not allowed to mix default, namespace, and named imports in any combination.
- // We could rewrite a default import as a named import (`import { default as name }`), but we currently
- // choose not to as a stylistic preference.
- if (isTypeOnly && newDefaultImport && newNamedImports) {
- coalescedImports.push(updateImportDeclarationAndClause(importDecl, newDefaultImport, /*namedBindings*/ undefined));
- coalescedImports.push(updateImportDeclarationAndClause((_a = namedImports[0]) !== null && _a !== void 0 ? _a : importDecl, /*name*/ undefined, newNamedImports));
- }
- else {
- coalescedImports.push(updateImportDeclarationAndClause(importDecl, newDefaultImport, newNamedImports));
- }
- }
- return coalescedImports;
- }
- OrganizeImports.coalesceImports = coalesceImports;
- /*
- * Returns entire import declarations because they may already have been rewritten and
- * may lack parent pointers. The desired parts can easily be recovered based on the
- * categorization.
- *
- * NB: There may be overlap between `defaultImports` and `namespaceImports`/`namedImports`.
- */
- function getCategorizedImports(importGroup) {
- var importWithoutClause;
- var typeOnlyImports = { defaultImports: [], namespaceImports: [], namedImports: [] };
- var regularImports = { defaultImports: [], namespaceImports: [], namedImports: [] };
- for (var _i = 0, importGroup_1 = importGroup; _i < importGroup_1.length; _i++) {
- var importDeclaration = importGroup_1[_i];
- if (importDeclaration.importClause === undefined) {
- // Only the first such import is interesting - the others are redundant.
- // Note: Unfortunately, we will lose trivia that was on this node.
- importWithoutClause = importWithoutClause || importDeclaration;
- continue;
- }
- var group_3 = importDeclaration.importClause.isTypeOnly ? typeOnlyImports : regularImports;
- var _a = importDeclaration.importClause, name = _a.name, namedBindings = _a.namedBindings;
- if (name) {
- group_3.defaultImports.push(importDeclaration);
- }
- if (namedBindings) {
- if (ts.isNamespaceImport(namedBindings)) {
- group_3.namespaceImports.push(importDeclaration);
- }
- else {
- group_3.namedImports.push(importDeclaration);
- }
- }
- }
- return {
- importWithoutClause: importWithoutClause,
- typeOnlyImports: typeOnlyImports,
- regularImports: regularImports,
- };
- }
- // Internal for testing
- /**
- * @param exportGroup a list of ExportDeclarations, all with the same module name.
- */
- function coalesceExports(exportGroup) {
- if (exportGroup.length === 0) {
- return exportGroup;
- }
- var _a = getCategorizedExports(exportGroup), exportWithoutClause = _a.exportWithoutClause, namedExports = _a.namedExports, typeOnlyExports = _a.typeOnlyExports;
- var coalescedExports = [];
- if (exportWithoutClause) {
- coalescedExports.push(exportWithoutClause);
- }
- for (var _i = 0, _b = [namedExports, typeOnlyExports]; _i < _b.length; _i++) {
- var exportGroup_1 = _b[_i];
- if (exportGroup_1.length === 0) {
- continue;
- }
- var newExportSpecifiers = [];
- newExportSpecifiers.push.apply(newExportSpecifiers, ts.flatMap(exportGroup_1, function (i) { return i.exportClause && ts.isNamedExports(i.exportClause) ? i.exportClause.elements : ts.emptyArray; }));
- var sortedExportSpecifiers = sortSpecifiers(newExportSpecifiers);
- var exportDecl = exportGroup_1[0];
- coalescedExports.push(ts.updateExportDeclaration(exportDecl, exportDecl.decorators, exportDecl.modifiers, exportDecl.exportClause && (ts.isNamedExports(exportDecl.exportClause) ?
- ts.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) :
- ts.updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name)), exportDecl.moduleSpecifier, exportDecl.isTypeOnly));
- }
- return coalescedExports;
- /*
- * Returns entire export declarations because they may already have been rewritten and
- * may lack parent pointers. The desired parts can easily be recovered based on the
- * categorization.
- */
- function getCategorizedExports(exportGroup) {
- var exportWithoutClause;
- var namedExports = [];
- var typeOnlyExports = [];
- for (var _i = 0, exportGroup_2 = exportGroup; _i < exportGroup_2.length; _i++) {
- var exportDeclaration = exportGroup_2[_i];
- if (exportDeclaration.exportClause === undefined) {
- // Only the first such export is interesting - the others are redundant.
- // Note: Unfortunately, we will lose trivia that was on this node.
- exportWithoutClause = exportWithoutClause || exportDeclaration;
- }
- else if (exportDeclaration.isTypeOnly) {
- typeOnlyExports.push(exportDeclaration);
- }
- else {
- namedExports.push(exportDeclaration);
- }
- }
- return {
- exportWithoutClause: exportWithoutClause,
- namedExports: namedExports,
- typeOnlyExports: typeOnlyExports,
- };
- }
- }
- OrganizeImports.coalesceExports = coalesceExports;
- function updateImportDeclarationAndClause(importDeclaration, name, namedBindings) {
- return ts.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.updateImportClause(importDeclaration.importClause, name, namedBindings, importDeclaration.importClause.isTypeOnly), // TODO: GH#18217
- importDeclaration.moduleSpecifier);
- }
- function sortSpecifiers(specifiers) {
- return ts.stableSort(specifiers, function (s1, s2) {
- return compareIdentifiers(s1.propertyName || s1.name, s2.propertyName || s2.name) ||
- compareIdentifiers(s1.name, s2.name);
- });
- }
- /* internal */ // Exported for testing
- function compareModuleSpecifiers(m1, m2) {
- var name1 = getExternalModuleName(m1);
- var name2 = getExternalModuleName(m2);
- return ts.compareBooleans(name1 === undefined, name2 === undefined) ||
- ts.compareBooleans(ts.isExternalModuleNameRelative(name1), ts.isExternalModuleNameRelative(name2)) ||
- ts.compareStringsCaseInsensitive(name1, name2);
- }
- OrganizeImports.compareModuleSpecifiers = compareModuleSpecifiers;
- function compareIdentifiers(s1, s2) {
- return ts.compareStringsCaseInsensitive(s1.text, s2.text);
- }
- })(OrganizeImports = ts.OrganizeImports || (ts.OrganizeImports = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var OutliningElementsCollector;
- (function (OutliningElementsCollector) {
- function collectElements(sourceFile, cancellationToken) {
- var res = [];
- addNodeOutliningSpans(sourceFile, cancellationToken, res);
- addRegionOutliningSpans(sourceFile, res);
- return res.sort(function (span1, span2) { return span1.textSpan.start - span2.textSpan.start; });
- }
- OutliningElementsCollector.collectElements = collectElements;
- function addNodeOutliningSpans(sourceFile, cancellationToken, out) {
- var depthRemaining = 40;
- var current = 0;
- // Includes the EOF Token so that comments which aren't attached to statements are included
- var statements = __spreadArrays(sourceFile.statements, [sourceFile.endOfFileToken]);
- var n = statements.length;
- while (current < n) {
- while (current < n && !ts.isAnyImportSyntax(statements[current])) {
- visitNonImportNode(statements[current]);
- current++;
- }
- if (current === n)
- break;
- var firstImport = current;
- while (current < n && ts.isAnyImportSyntax(statements[current])) {
- addOutliningForLeadingCommentsForNode(statements[current], sourceFile, cancellationToken, out);
- current++;
- }
- var lastImport = current - 1;
- if (lastImport !== firstImport) {
- out.push(createOutliningSpanFromBounds(ts.findChildOfKind(statements[firstImport], 96 /* ImportKeyword */, sourceFile).getStart(sourceFile), statements[lastImport].getEnd(), "imports" /* Imports */));
- }
- }
- function visitNonImportNode(n) {
- var _a;
- if (depthRemaining === 0)
- return;
- cancellationToken.throwIfCancellationRequested();
- if (ts.isDeclaration(n) || n.kind === 1 /* EndOfFileToken */) {
- addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out);
- }
- if (isFunctionExpressionAssignedToVariable(n)) {
- addOutliningForLeadingCommentsForNode(n.parent.parent.parent, sourceFile, cancellationToken, out);
- }
- var span = getOutliningSpanForNode(n, sourceFile);
- if (span)
- out.push(span);
- depthRemaining--;
- if (ts.isCallExpression(n)) {
- depthRemaining++;
- visitNonImportNode(n.expression);
- depthRemaining--;
- n.arguments.forEach(visitNonImportNode);
- (_a = n.typeArguments) === null || _a === void 0 ? void 0 : _a.forEach(visitNonImportNode);
- }
- else if (ts.isIfStatement(n) && n.elseStatement && ts.isIfStatement(n.elseStatement)) {
- // Consider an 'else if' to be on the same depth as the 'if'.
- visitNonImportNode(n.expression);
- visitNonImportNode(n.thenStatement);
- depthRemaining++;
- visitNonImportNode(n.elseStatement);
- depthRemaining--;
- }
- else {
- n.forEachChild(visitNonImportNode);
- }
- depthRemaining++;
- }
- function isFunctionExpressionAssignedToVariable(n) {
- if (!ts.isFunctionExpression(n) && !ts.isArrowFunction(n)) {
- return false;
- }
- var ancestor = ts.findAncestor(n, ts.isVariableStatement);
- return !!ancestor && ts.getSingleInitializerOfVariableStatementOrPropertyDeclaration(ancestor) === n;
- }
- }
- function addRegionOutliningSpans(sourceFile, out) {
- var regions = [];
- var lineStarts = sourceFile.getLineStarts();
- for (var _i = 0, lineStarts_1 = lineStarts; _i < lineStarts_1.length; _i++) {
- var currentLineStart = lineStarts_1[_i];
- var lineEnd = sourceFile.getLineEndOfPosition(currentLineStart);
- var lineText = sourceFile.text.substring(currentLineStart, lineEnd);
- var result = isRegionDelimiter(lineText);
- if (!result || ts.isInComment(sourceFile, currentLineStart)) {
- continue;
- }
- if (!result[1]) {
- var span = ts.createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd);
- regions.push(createOutliningSpan(span, "region" /* Region */, span, /*autoCollapse*/ false, result[2] || "#region"));
- }
- else {
- var region = regions.pop();
- if (region) {
- region.textSpan.length = lineEnd - region.textSpan.start;
- region.hintSpan.length = lineEnd - region.textSpan.start;
- out.push(region);
- }
- }
- }
- }
- var regionDelimiterRegExp = /^\s*\/\/\s*#(end)?region(?:\s+(.*))?(?:\r)?$/;
- function isRegionDelimiter(lineText) {
- return regionDelimiterRegExp.exec(lineText);
- }
- function addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out) {
- var comments = ts.getLeadingCommentRangesOfNode(n, sourceFile);
- if (!comments)
- return;
- var firstSingleLineCommentStart = -1;
- var lastSingleLineCommentEnd = -1;
- var singleLineCommentCount = 0;
- var sourceText = sourceFile.getFullText();
- for (var _i = 0, comments_1 = comments; _i < comments_1.length; _i++) {
- var _a = comments_1[_i], kind = _a.kind, pos = _a.pos, end = _a.end;
- cancellationToken.throwIfCancellationRequested();
- switch (kind) {
- case 2 /* SingleLineCommentTrivia */:
- // never fold region delimiters into single-line comment regions
- var commentText = sourceText.slice(pos, end);
- if (isRegionDelimiter(commentText)) {
- combineAndAddMultipleSingleLineComments();
- singleLineCommentCount = 0;
- break;
- }
- // For single line comments, combine consecutive ones (2 or more) into
- // a single span from the start of the first till the end of the last
- if (singleLineCommentCount === 0) {
- firstSingleLineCommentStart = pos;
- }
- lastSingleLineCommentEnd = end;
- singleLineCommentCount++;
- break;
- case 3 /* MultiLineCommentTrivia */:
- combineAndAddMultipleSingleLineComments();
- out.push(createOutliningSpanFromBounds(pos, end, "comment" /* Comment */));
- singleLineCommentCount = 0;
- break;
- default:
- ts.Debug.assertNever(kind);
- }
- }
- combineAndAddMultipleSingleLineComments();
- function combineAndAddMultipleSingleLineComments() {
- // Only outline spans of two or more consecutive single line comments
- if (singleLineCommentCount > 1) {
- out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, "comment" /* Comment */));
- }
- }
- }
- function createOutliningSpanFromBounds(pos, end, kind) {
- return createOutliningSpan(ts.createTextSpanFromBounds(pos, end), kind);
- }
- function getOutliningSpanForNode(n, sourceFile) {
- switch (n.kind) {
- case 223 /* Block */:
- if (ts.isFunctionLike(n.parent)) {
- return functionSpan(n.parent, n, sourceFile);
- }
- // Check if the block is standalone, or 'attached' to some parent statement.
- // If the latter, we want to collapse the block, but consider its hint span
- // to be the entire span of the parent.
- switch (n.parent.kind) {
- case 228 /* DoStatement */:
- case 231 /* ForInStatement */:
- case 232 /* ForOfStatement */:
- case 230 /* ForStatement */:
- case 227 /* IfStatement */:
- case 229 /* WhileStatement */:
- case 236 /* WithStatement */:
- case 280 /* CatchClause */:
- return spanForNode(n.parent);
- case 240 /* TryStatement */:
- // Could be the try-block, or the finally-block.
- var tryStatement = n.parent;
- if (tryStatement.tryBlock === n) {
- return spanForNode(n.parent);
- }
- else if (tryStatement.finallyBlock === n) {
- var node = ts.findChildOfKind(tryStatement, 92 /* FinallyKeyword */, sourceFile);
- if (node)
- return spanForNode(node);
- }
- // falls through
- default:
- // Block was a standalone block. In this case we want to only collapse
- // the span of the block, independent of any parent span.
- return createOutliningSpan(ts.createTextSpanFromNode(n, sourceFile), "code" /* Code */);
- }
- case 250 /* ModuleBlock */:
- return spanForNode(n.parent);
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 246 /* InterfaceDeclaration */:
- case 248 /* EnumDeclaration */:
- case 251 /* CaseBlock */:
- case 173 /* TypeLiteral */:
- return spanForNode(n);
- case 277 /* CaseClause */:
- case 278 /* DefaultClause */:
- return spanForNodeArray(n.statements);
- case 193 /* ObjectLiteralExpression */:
- return spanForObjectOrArrayLiteral(n);
- case 192 /* ArrayLiteralExpression */:
- return spanForObjectOrArrayLiteral(n, 22 /* OpenBracketToken */);
- case 266 /* JsxElement */:
- return spanForJSXElement(n);
- case 270 /* JsxFragment */:
- return spanForJSXFragment(n);
- case 267 /* JsxSelfClosingElement */:
- case 268 /* JsxOpeningElement */:
- return spanForJSXAttributes(n.attributes);
- case 211 /* TemplateExpression */:
- case 14 /* NoSubstitutionTemplateLiteral */:
- return spanForTemplateLiteral(n);
- }
- function spanForJSXElement(node) {
- var textSpan = ts.createTextSpanFromBounds(node.openingElement.getStart(sourceFile), node.closingElement.getEnd());
- var tagName = node.openingElement.tagName.getText(sourceFile);
- var bannerText = "<" + tagName + ">..." + tagName + ">";
- return createOutliningSpan(textSpan, "code" /* Code */, textSpan, /*autoCollapse*/ false, bannerText);
- }
- function spanForJSXFragment(node) {
- var textSpan = ts.createTextSpanFromBounds(node.openingFragment.getStart(sourceFile), node.closingFragment.getEnd());
- var bannerText = "<>...>";
- return createOutliningSpan(textSpan, "code" /* Code */, textSpan, /*autoCollapse*/ false, bannerText);
- }
- function spanForJSXAttributes(node) {
- if (node.properties.length === 0) {
- return undefined;
- }
- return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), "code" /* Code */);
- }
- function spanForTemplateLiteral(node) {
- if (node.kind === 14 /* NoSubstitutionTemplateLiteral */ && node.text.length === 0) {
- return undefined;
- }
- return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), "code" /* Code */);
- }
- function spanForObjectOrArrayLiteral(node, open) {
- if (open === void 0) { open = 18 /* OpenBraceToken */; }
- // If the block has no leading keywords and is inside an array literal or call expression,
- // we only want to collapse the span of the block.
- // Otherwise, the collapsed section will include the end of the previous line.
- return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !ts.isArrayLiteralExpression(node.parent) && !ts.isCallExpression(node.parent), open);
- }
- function spanForNode(hintSpanNode, autoCollapse, useFullStart, open, close) {
- if (autoCollapse === void 0) { autoCollapse = false; }
- if (useFullStart === void 0) { useFullStart = true; }
- if (open === void 0) { open = 18 /* OpenBraceToken */; }
- if (close === void 0) { close = open === 18 /* OpenBraceToken */ ? 19 /* CloseBraceToken */ : 23 /* CloseBracketToken */; }
- var openToken = ts.findChildOfKind(n, open, sourceFile);
- var closeToken = ts.findChildOfKind(n, close, sourceFile);
- return openToken && closeToken && spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse, useFullStart);
- }
- function spanForNodeArray(nodeArray) {
- return nodeArray.length ? createOutliningSpan(ts.createTextSpanFromRange(nodeArray), "code" /* Code */) : undefined;
- }
- }
- function functionSpan(node, body, sourceFile) {
- var openToken = ts.isNodeArrayMultiLine(node.parameters, sourceFile)
- ? ts.findChildOfKind(node, 20 /* OpenParenToken */, sourceFile)
- : ts.findChildOfKind(body, 18 /* OpenBraceToken */, sourceFile);
- var closeToken = ts.findChildOfKind(body, 19 /* CloseBraceToken */, sourceFile);
- return openToken && closeToken && spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ node.kind !== 202 /* ArrowFunction */);
- }
- function spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse, useFullStart) {
- if (autoCollapse === void 0) { autoCollapse = false; }
- if (useFullStart === void 0) { useFullStart = true; }
- var textSpan = ts.createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd());
- return createOutliningSpan(textSpan, "code" /* Code */, ts.createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse);
- }
- function createOutliningSpan(textSpan, kind, hintSpan, autoCollapse, bannerText) {
- if (hintSpan === void 0) { hintSpan = textSpan; }
- if (autoCollapse === void 0) { autoCollapse = false; }
- if (bannerText === void 0) { bannerText = "..."; }
- return { textSpan: textSpan, kind: kind, hintSpan: hintSpan, bannerText: bannerText, autoCollapse: autoCollapse };
- }
- })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- // Note(cyrusn): this enum is ordered from strongest match type to weakest match type.
- var PatternMatchKind;
- (function (PatternMatchKind) {
- PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact";
- PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix";
- PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring";
- PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase";
- })(PatternMatchKind = ts.PatternMatchKind || (ts.PatternMatchKind = {}));
- function createPatternMatch(kind, isCaseSensitive) {
- return {
- kind: kind,
- isCaseSensitive: isCaseSensitive
- };
- }
- function createPatternMatcher(pattern) {
- // We'll often see the same candidate string many times when searching (For example, when
- // we see the name of a module that is used everywhere, or the name of an overload). As
- // such, we cache the information we compute about the candidate for the life of this
- // pattern matcher so we don't have to compute it multiple times.
- var stringToWordSpans = ts.createMap();
- var dotSeparatedSegments = pattern.trim().split(".").map(function (p) { return createSegment(p.trim()); });
- // A segment is considered invalid if we couldn't find any words in it.
- if (dotSeparatedSegments.some(function (segment) { return !segment.subWordTextChunks.length; }))
- return undefined;
- return {
- getFullMatch: function (containers, candidate) { return getFullMatch(containers, candidate, dotSeparatedSegments, stringToWordSpans); },
- getMatchForLastSegmentOfPattern: function (candidate) { return matchSegment(candidate, ts.last(dotSeparatedSegments), stringToWordSpans); },
- patternContainsDots: dotSeparatedSegments.length > 1
- };
- }
- ts.createPatternMatcher = createPatternMatcher;
- function getFullMatch(candidateContainers, candidate, dotSeparatedSegments, stringToWordSpans) {
- // First, check that the last part of the dot separated pattern matches the name of the
- // candidate. If not, then there's no point in proceeding and doing the more
- // expensive work.
- var candidateMatch = matchSegment(candidate, ts.last(dotSeparatedSegments), stringToWordSpans);
- if (!candidateMatch) {
- return undefined;
- }
- // -1 because the last part was checked against the name, and only the rest
- // of the parts are checked against the container.
- if (dotSeparatedSegments.length - 1 > candidateContainers.length) {
- // There weren't enough container parts to match against the pattern parts.
- // So this definitely doesn't match.
- return undefined;
- }
- var bestMatch;
- for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i -= 1, j -= 1) {
- bestMatch = betterMatch(bestMatch, matchSegment(candidateContainers[j], dotSeparatedSegments[i], stringToWordSpans));
- }
- return bestMatch;
- }
- function getWordSpans(word, stringToWordSpans) {
- var spans = stringToWordSpans.get(word);
- if (!spans) {
- stringToWordSpans.set(word, spans = breakIntoWordSpans(word));
- }
- return spans;
- }
- function matchTextChunk(candidate, chunk, stringToWordSpans) {
- var index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
- if (index === 0) {
- // a) Check if the word is a prefix of the candidate, in a case insensitive or
- // sensitive manner. If it does, return that there was an exact match if the word and candidate are the same length, else a prefix match.
- return createPatternMatch(chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text));
- }
- if (chunk.isLowerCase) {
- if (index === -1)
- return undefined;
- // b) If the part is entirely lowercase, then check if it is contained anywhere in the
- // candidate in a case insensitive manner. If so, return that there was a substring
- // match.
- //
- // Note: We only have a substring match if the lowercase part is prefix match of some
- // word part. That way we don't match something like 'Class' when the user types 'a'.
- // But we would match 'FooAttribute' (since 'Attribute' starts with 'a').
- var wordSpans = getWordSpans(candidate, stringToWordSpans);
- for (var _i = 0, wordSpans_1 = wordSpans; _i < wordSpans_1.length; _i++) {
- var span = wordSpans_1[_i];
- if (partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ true)) {
- return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false));
- }
- }
- // c) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries?
- // We could check every character boundary start of the candidate for the pattern. However, that's
- // an m * n operation in the wost case. Instead, find the first instance of the pattern
- // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to
- // filter the list based on a substring that starts on a capital letter and also with a lowercase one.
- // (Pattern: fogbar, Candidate: quuxfogbarFogBar).
- if (chunk.text.length < candidate.length && isUpperCaseLetter(candidate.charCodeAt(index))) {
- return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ false);
- }
- }
- else {
- // d) If the part was not entirely lowercase, then check if it is contained in the
- // candidate in a case *sensitive* manner. If so, return that there was a substring
- // match.
- if (candidate.indexOf(chunk.text) > 0) {
- return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ true);
- }
- // e) If the part was not entirely lowercase, then attempt a camel cased match as well.
- if (chunk.characterSpans.length > 0) {
- var candidateParts = getWordSpans(candidate, stringToWordSpans);
- var isCaseSensitive = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false) ? true
- : tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true) ? false : undefined;
- if (isCaseSensitive !== undefined) {
- return createPatternMatch(PatternMatchKind.camelCase, isCaseSensitive);
- }
- }
- }
- }
- function matchSegment(candidate, segment, stringToWordSpans) {
- // First check if the segment matches as is. This is also useful if the segment contains
- // characters we would normally strip when splitting into parts that we also may want to
- // match in the candidate. For example if the segment is "@int" and the candidate is
- // "@int", then that will show up as an exact match here.
- //
- // Note: if the segment contains a space or an asterisk then we must assume that it's a
- // multi-word segment.
- if (every(segment.totalTextChunk.text, function (ch) { return ch !== 32 /* space */ && ch !== 42 /* asterisk */; })) {
- var match = matchTextChunk(candidate, segment.totalTextChunk, stringToWordSpans);
- if (match)
- return match;
- }
- // The logic for pattern matching is now as follows:
- //
- // 1) Break the segment passed in into words. Breaking is rather simple and a
- // good way to think about it that if gives you all the individual alphanumeric words
- // of the pattern.
- //
- // 2) For each word try to match the word against the candidate value.
- //
- // 3) Matching is as follows:
- //
- // a) Check if the word is a prefix of the candidate, in a case insensitive or
- // sensitive manner. If it does, return that there was an exact match if the word and candidate are the same length, else a prefix match.
- //
- // If the word is entirely lowercase:
- // b) Then check if it is contained anywhere in the
- // candidate in a case insensitive manner. If so, return that there was a substring
- // match.
- //
- // Note: We only have a substring match if the lowercase part is prefix match of
- // some word part. That way we don't match something like 'Class' when the user
- // types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with
- // 'a').
- //
- // c) The word is all lower case. Is it a case insensitive substring of the candidate starting
- // on a part boundary of the candidate?
- //
- // Else:
- // d) If the word was not entirely lowercase, then check if it is contained in the
- // candidate in a case *sensitive* manner. If so, return that there was a substring
- // match.
- //
- // e) If the word was not entirely lowercase, then attempt a camel cased match as
- // well.
- //
- // Only if all words have some sort of match is the pattern considered matched.
- var subWordTextChunks = segment.subWordTextChunks;
- var bestMatch;
- for (var _i = 0, subWordTextChunks_1 = subWordTextChunks; _i < subWordTextChunks_1.length; _i++) {
- var subWordTextChunk = subWordTextChunks_1[_i];
- bestMatch = betterMatch(bestMatch, matchTextChunk(candidate, subWordTextChunk, stringToWordSpans));
- }
- return bestMatch;
- }
- function betterMatch(a, b) {
- return ts.min(a, b, compareMatches);
- }
- function compareMatches(a, b) {
- return a === undefined ? 1 /* GreaterThan */ : b === undefined ? -1 /* LessThan */
- : ts.compareValues(a.kind, b.kind) || ts.compareBooleans(!a.isCaseSensitive, !b.isCaseSensitive);
- }
- function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) {
- if (patternSpan === void 0) { patternSpan = { start: 0, length: pattern.length }; }
- return patternSpan.length <= candidateSpan.length // If pattern part is longer than the candidate part there can never be a match.
- && everyInRange(0, patternSpan.length, function (i) { return equalChars(pattern.charCodeAt(patternSpan.start + i), candidate.charCodeAt(candidateSpan.start + i), ignoreCase); });
- }
- function equalChars(ch1, ch2, ignoreCase) {
- return ignoreCase ? toLowerCase(ch1) === toLowerCase(ch2) : ch1 === ch2;
- }
- function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) {
- var chunkCharacterSpans = chunk.characterSpans;
- // Note: we may have more pattern parts than candidate parts. This is because multiple
- // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI".
- // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U
- // and I will both match in UI.
- var currentCandidate = 0;
- var currentChunkSpan = 0;
- var firstMatch;
- var contiguous;
- while (true) {
- // Let's consider our termination cases
- if (currentChunkSpan === chunkCharacterSpans.length) {
- return true;
- }
- else if (currentCandidate === candidateParts.length) {
- // No match, since we still have more of the pattern to hit
- return false;
- }
- var candidatePart = candidateParts[currentCandidate];
- var gotOneMatchThisCandidate = false;
- // Consider the case of matching SiUI against SimpleUIElement. The candidate parts
- // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si'
- // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to
- // still keep matching pattern parts against that candidate part.
- for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) {
- var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan];
- if (gotOneMatchThisCandidate) {
- // We've already gotten one pattern part match in this candidate. We will
- // only continue trying to consumer pattern parts if the last part and this
- // part are both upper case.
- if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) ||
- !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) {
- break;
- }
- }
- if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) {
- break;
- }
- gotOneMatchThisCandidate = true;
- firstMatch = firstMatch === undefined ? currentCandidate : firstMatch;
- // If we were contiguous, then keep that value. If we weren't, then keep that
- // value. If we don't know, then set the value to 'true' as an initial match is
- // obviously contiguous.
- contiguous = contiguous === undefined ? true : contiguous;
- candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length);
- }
- // Check if we matched anything at all. If we didn't, then we need to unset the
- // contiguous bit if we currently had it set.
- // If we haven't set the bit yet, then that means we haven't matched anything so
- // far, and we don't want to change that.
- if (!gotOneMatchThisCandidate && contiguous !== undefined) {
- contiguous = false;
- }
- // Move onto the next candidate.
- currentCandidate++;
- }
- }
- function createSegment(text) {
- return {
- totalTextChunk: createTextChunk(text),
- subWordTextChunks: breakPatternIntoTextChunks(text)
- };
- }
- function isUpperCaseLetter(ch) {
- // Fast check for the ascii range.
- if (ch >= 65 /* A */ && ch <= 90 /* Z */) {
- return true;
- }
- if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 99 /* Latest */)) {
- return false;
- }
- // TODO: find a way to determine this for any unicode characters in a
- // non-allocating manner.
- var str = String.fromCharCode(ch);
- return str === str.toUpperCase();
- }
- function isLowerCaseLetter(ch) {
- // Fast check for the ascii range.
- if (ch >= 97 /* a */ && ch <= 122 /* z */) {
- return true;
- }
- if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 99 /* Latest */)) {
- return false;
- }
- // TODO: find a way to determine this for any unicode characters in a
- // non-allocating manner.
- var str = String.fromCharCode(ch);
- return str === str.toLowerCase();
- }
- // Assumes 'value' is already lowercase.
- function indexOfIgnoringCase(str, value) {
- var n = str.length - value.length;
- var _loop_6 = function (start) {
- if (every(value, function (valueChar, i) { return toLowerCase(str.charCodeAt(i + start)) === valueChar; })) {
- return { value: start };
- }
- };
- for (var start = 0; start <= n; start++) {
- var state_1 = _loop_6(start);
- if (typeof state_1 === "object")
- return state_1.value;
- }
- return -1;
- }
- function toLowerCase(ch) {
- // Fast convert for the ascii range.
- if (ch >= 65 /* A */ && ch <= 90 /* Z */) {
- return 97 /* a */ + (ch - 65 /* A */);
- }
- if (ch < 127 /* maxAsciiCharacter */) {
- return ch;
- }
- // TODO: find a way to compute this for any unicode characters in a
- // non-allocating manner.
- return String.fromCharCode(ch).toLowerCase().charCodeAt(0);
- }
- function isDigit(ch) {
- // TODO(cyrusn): Find a way to support this for unicode digits.
- return ch >= 48 /* _0 */ && ch <= 57 /* _9 */;
- }
- function isWordChar(ch) {
- return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */;
- }
- function breakPatternIntoTextChunks(pattern) {
- var result = [];
- var wordStart = 0;
- var wordLength = 0;
- for (var i = 0; i < pattern.length; i++) {
- var ch = pattern.charCodeAt(i);
- if (isWordChar(ch)) {
- if (wordLength === 0) {
- wordStart = i;
- }
- wordLength++;
- }
- else {
- if (wordLength > 0) {
- result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
- wordLength = 0;
- }
- }
- }
- if (wordLength > 0) {
- result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
- }
- return result;
- }
- function createTextChunk(text) {
- var textLowerCase = text.toLowerCase();
- return {
- text: text,
- textLowerCase: textLowerCase,
- isLowerCase: text === textLowerCase,
- characterSpans: breakIntoCharacterSpans(text)
- };
- }
- function breakIntoCharacterSpans(identifier) {
- return breakIntoSpans(identifier, /*word:*/ false);
- }
- ts.breakIntoCharacterSpans = breakIntoCharacterSpans;
- function breakIntoWordSpans(identifier) {
- return breakIntoSpans(identifier, /*word:*/ true);
- }
- ts.breakIntoWordSpans = breakIntoWordSpans;
- function breakIntoSpans(identifier, word) {
- var result = [];
- var wordStart = 0;
- for (var i = 1; i < identifier.length; i++) {
- var lastIsDigit = isDigit(identifier.charCodeAt(i - 1));
- var currentIsDigit = isDigit(identifier.charCodeAt(i));
- var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i);
- var hasTransitionFromUpperToLower = word && transitionFromUpperToLower(identifier, i, wordStart);
- if (charIsPunctuation(identifier.charCodeAt(i - 1)) ||
- charIsPunctuation(identifier.charCodeAt(i)) ||
- lastIsDigit !== currentIsDigit ||
- hasTransitionFromLowerToUpper ||
- hasTransitionFromUpperToLower) {
- if (!isAllPunctuation(identifier, wordStart, i)) {
- result.push(ts.createTextSpan(wordStart, i - wordStart));
- }
- wordStart = i;
- }
- }
- if (!isAllPunctuation(identifier, wordStart, identifier.length)) {
- result.push(ts.createTextSpan(wordStart, identifier.length - wordStart));
- }
- return result;
- }
- function charIsPunctuation(ch) {
- switch (ch) {
- case 33 /* exclamation */:
- case 34 /* doubleQuote */:
- case 35 /* hash */:
- case 37 /* percent */:
- case 38 /* ampersand */:
- case 39 /* singleQuote */:
- case 40 /* openParen */:
- case 41 /* closeParen */:
- case 42 /* asterisk */:
- case 44 /* comma */:
- case 45 /* minus */:
- case 46 /* dot */:
- case 47 /* slash */:
- case 58 /* colon */:
- case 59 /* semicolon */:
- case 63 /* question */:
- case 64 /* at */:
- case 91 /* openBracket */:
- case 92 /* backslash */:
- case 93 /* closeBracket */:
- case 95 /* _ */:
- case 123 /* openBrace */:
- case 125 /* closeBrace */:
- return true;
- }
- return false;
- }
- function isAllPunctuation(identifier, start, end) {
- return every(identifier, function (ch) { return charIsPunctuation(ch) && ch !== 95 /* _ */; }, start, end);
- }
- function transitionFromUpperToLower(identifier, index, wordStart) {
- // Cases this supports:
- // 1) IDisposable -> I, Disposable
- // 2) UIElement -> UI, Element
- // 3) HTMLDocument -> HTML, Document
- //
- // etc.
- // We have a transition from an upper to a lower letter here. But we only
- // want to break if all the letters that preceded are uppercase. i.e. if we
- // have "Foo" we don't want to break that into "F, oo". But if we have
- // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI,
- // Foo". i.e. the last uppercase letter belongs to the lowercase letters
- // that follows. Note: this will make the following not split properly:
- // "HELLOthere". However, these sorts of names do not show up in .Net
- // programs.
- return index !== wordStart
- && index + 1 < identifier.length
- && isUpperCaseLetter(identifier.charCodeAt(index))
- && isLowerCaseLetter(identifier.charCodeAt(index + 1))
- && every(identifier, isUpperCaseLetter, wordStart, index);
- }
- function transitionFromLowerToUpper(identifier, word, index) {
- var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1));
- var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
- // See if the casing indicates we're starting a new word. Note: if we're breaking on
- // words, then just seeing an upper case character isn't enough. Instead, it has to
- // be uppercase and the previous character can't be uppercase.
- //
- // For example, breaking "AddMetadata" on words would make: Add Metadata
- //
- // on characters would be: A dd M etadata
- //
- // Break "AM" on words would be: AM
- //
- // on characters would be: A M
- //
- // We break the search string on characters. But we break the symbol name on words.
- return currentIsUpper && (!word || !lastIsUpper);
- }
- function everyInRange(start, end, pred) {
- for (var i = start; i < end; i++) {
- if (!pred(i)) {
- return false;
- }
- }
- return true;
- }
- function every(s, pred, start, end) {
- if (start === void 0) { start = 0; }
- if (end === void 0) { end = s.length; }
- return everyInRange(start, end, function (i) { return pred(s.charCodeAt(i), i); });
- }
-})(ts || (ts = {}));
-var ts;
-(function (ts) {
- function preProcessFile(sourceText, readImportFiles, detectJavaScriptImports) {
- if (readImportFiles === void 0) { readImportFiles = true; }
- if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; }
- var pragmaContext = {
- languageVersion: 1 /* ES5 */,
- pragmas: undefined,
- checkJsDirective: undefined,
- referencedFiles: [],
- typeReferenceDirectives: [],
- libReferenceDirectives: [],
- amdDependencies: [],
- hasNoDefaultLib: undefined,
- moduleName: undefined
- };
- var importedFiles = [];
- var ambientExternalModules;
- var lastToken;
- var currentToken;
- var braceNesting = 0;
- // assume that text represent an external module if it contains at least one top level import/export
- // ambient modules that are found inside external modules are interpreted as module augmentations
- var externalModule = false;
- function nextToken() {
- lastToken = currentToken;
- currentToken = ts.scanner.scan();
- if (currentToken === 18 /* OpenBraceToken */) {
- braceNesting++;
- }
- else if (currentToken === 19 /* CloseBraceToken */) {
- braceNesting--;
- }
- return currentToken;
- }
- function getFileReference() {
- var fileName = ts.scanner.getTokenValue();
- var pos = ts.scanner.getTokenPos();
- return { fileName: fileName, pos: pos, end: pos + fileName.length };
- }
- function recordAmbientExternalModule() {
- if (!ambientExternalModules) {
- ambientExternalModules = [];
- }
- ambientExternalModules.push({ ref: getFileReference(), depth: braceNesting });
- }
- function recordModuleName() {
- importedFiles.push(getFileReference());
- markAsExternalModuleIfTopLevel();
- }
- function markAsExternalModuleIfTopLevel() {
- if (braceNesting === 0) {
- externalModule = true;
- }
- }
- /**
- * Returns true if at least one token was consumed from the stream
- */
- function tryConsumeDeclare() {
- var token = ts.scanner.getToken();
- if (token === 130 /* DeclareKeyword */) {
- // declare module "mod"
- token = nextToken();
- if (token === 135 /* ModuleKeyword */) {
- token = nextToken();
- if (token === 10 /* StringLiteral */) {
- recordAmbientExternalModule();
- }
- }
- return true;
- }
- return false;
- }
- /**
- * Returns true if at least one token was consumed from the stream
- */
- function tryConsumeImport() {
- if (lastToken === 24 /* DotToken */) {
- return false;
- }
- var token = ts.scanner.getToken();
- if (token === 96 /* ImportKeyword */) {
- token = nextToken();
- if (token === 20 /* OpenParenToken */) {
- token = nextToken();
- if (token === 10 /* StringLiteral */ || token === 14 /* NoSubstitutionTemplateLiteral */) {
- // import("mod");
- recordModuleName();
- return true;
- }
- }
- else if (token === 10 /* StringLiteral */) {
- // import "mod";
- recordModuleName();
- return true;
- }
- else {
- if (token === 145 /* TypeKeyword */) {
- var skipTypeKeyword = ts.scanner.lookAhead(function () {
- var token = ts.scanner.scan();
- return token !== 149 /* FromKeyword */ && (token === 41 /* AsteriskToken */ ||
- token === 18 /* OpenBraceToken */ ||
- token === 75 /* Identifier */ ||
- ts.isKeyword(token));
- });
- if (skipTypeKeyword) {
- token = nextToken();
- }
- }
- if (token === 75 /* Identifier */ || ts.isKeyword(token)) {
- token = nextToken();
- if (token === 149 /* FromKeyword */) {
- token = nextToken();
- if (token === 10 /* StringLiteral */) {
- // import d from "mod";
- recordModuleName();
- return true;
- }
- }
- else if (token === 62 /* EqualsToken */) {
- if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) {
- return true;
- }
- }
- else if (token === 27 /* CommaToken */) {
- // consume comma and keep going
- token = nextToken();
- }
- else {
- // unknown syntax
- return true;
- }
- }
- if (token === 18 /* OpenBraceToken */) {
- token = nextToken();
- // consume "{ a as B, c, d as D}" clauses
- // make sure that it stops on EOF
- while (token !== 19 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) {
- token = nextToken();
- }
- if (token === 19 /* CloseBraceToken */) {
- token = nextToken();
- if (token === 149 /* FromKeyword */) {
- token = nextToken();
- if (token === 10 /* StringLiteral */) {
- // import {a as A} from "mod";
- // import d, {a, b as B} from "mod"
- recordModuleName();
- }
- }
- }
- }
- else if (token === 41 /* AsteriskToken */) {
- token = nextToken();
- if (token === 123 /* AsKeyword */) {
- token = nextToken();
- if (token === 75 /* Identifier */ || ts.isKeyword(token)) {
- token = nextToken();
- if (token === 149 /* FromKeyword */) {
- token = nextToken();
- if (token === 10 /* StringLiteral */) {
- // import * as NS from "mod"
- // import d, * as NS from "mod"
- recordModuleName();
- }
- }
- }
- }
- }
- }
- return true;
- }
- return false;
- }
- function tryConsumeExport() {
- var token = ts.scanner.getToken();
- if (token === 89 /* ExportKeyword */) {
- markAsExternalModuleIfTopLevel();
- token = nextToken();
- if (token === 145 /* TypeKeyword */) {
- var skipTypeKeyword = ts.scanner.lookAhead(function () {
- var token = ts.scanner.scan();
- return token === 41 /* AsteriskToken */ ||
- token === 18 /* OpenBraceToken */;
- });
- if (skipTypeKeyword) {
- token = nextToken();
- }
- }
- if (token === 18 /* OpenBraceToken */) {
- token = nextToken();
- // consume "{ a as B, c, d as D}" clauses
- // make sure it stops on EOF
- while (token !== 19 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) {
- token = nextToken();
- }
- if (token === 19 /* CloseBraceToken */) {
- token = nextToken();
- if (token === 149 /* FromKeyword */) {
- token = nextToken();
- if (token === 10 /* StringLiteral */) {
- // export {a as A} from "mod";
- // export {a, b as B} from "mod"
- recordModuleName();
- }
- }
- }
- }
- else if (token === 41 /* AsteriskToken */) {
- token = nextToken();
- if (token === 149 /* FromKeyword */) {
- token = nextToken();
- if (token === 10 /* StringLiteral */) {
- // export * from "mod"
- recordModuleName();
- }
- }
- }
- else if (token === 96 /* ImportKeyword */) {
- token = nextToken();
- if (token === 145 /* TypeKeyword */) {
- var skipTypeKeyword = ts.scanner.lookAhead(function () {
- var token = ts.scanner.scan();
- return token === 75 /* Identifier */ ||
- ts.isKeyword(token);
- });
- if (skipTypeKeyword) {
- token = nextToken();
- }
- }
- if (token === 75 /* Identifier */ || ts.isKeyword(token)) {
- token = nextToken();
- if (token === 62 /* EqualsToken */) {
- if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) {
- return true;
- }
- }
- }
- }
- return true;
- }
- return false;
- }
- function tryConsumeRequireCall(skipCurrentToken, allowTemplateLiterals) {
- if (allowTemplateLiterals === void 0) { allowTemplateLiterals = false; }
- var token = skipCurrentToken ? nextToken() : ts.scanner.getToken();
- if (token === 139 /* RequireKeyword */) {
- token = nextToken();
- if (token === 20 /* OpenParenToken */) {
- token = nextToken();
- if (token === 10 /* StringLiteral */ ||
- allowTemplateLiterals && token === 14 /* NoSubstitutionTemplateLiteral */) {
- // require("mod");
- recordModuleName();
- }
- }
- return true;
- }
- return false;
- }
- function tryConsumeDefine() {
- var token = ts.scanner.getToken();
- if (token === 75 /* Identifier */ && ts.scanner.getTokenValue() === "define") {
- token = nextToken();
- if (token !== 20 /* OpenParenToken */) {
- return true;
- }
- token = nextToken();
- if (token === 10 /* StringLiteral */ || token === 14 /* NoSubstitutionTemplateLiteral */) {
- // looks like define ("modname", ... - skip string literal and comma
- token = nextToken();
- if (token === 27 /* CommaToken */) {
- token = nextToken();
- }
- else {
- // unexpected token
- return true;
- }
- }
- // should be start of dependency list
- if (token !== 22 /* OpenBracketToken */) {
- return true;
- }
- // skip open bracket
- token = nextToken();
- // scan until ']' or EOF
- while (token !== 23 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) {
- // record string literals as module names
- if (token === 10 /* StringLiteral */ || token === 14 /* NoSubstitutionTemplateLiteral */) {
- recordModuleName();
- }
- token = nextToken();
- }
- return true;
- }
- return false;
- }
- function processImports() {
- ts.scanner.setText(sourceText);
- nextToken();
- // Look for:
- // import "mod";
- // import d from "mod"
- // import {a as A } from "mod";
- // import * as NS from "mod"
- // import d, {a, b as B} from "mod"
- // import i = require("mod");
- // import("mod");
- // export * from "mod"
- // export {a as b} from "mod"
- // export import i = require("mod")
- // (for JavaScript files) require("mod")
- // Do not look for:
- // AnySymbol.import("mod")
- // AnySymbol.nested.import("mod")
- while (true) {
- if (ts.scanner.getToken() === 1 /* EndOfFileToken */) {
- break;
- }
- // check if at least one of alternative have moved scanner forward
- if (tryConsumeDeclare() ||
- tryConsumeImport() ||
- tryConsumeExport() ||
- (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false, /*allowTemplateLiterals*/ true) ||
- tryConsumeDefine()))) {
- continue;
- }
- else {
- nextToken();
- }
- }
- ts.scanner.setText(undefined);
- }
- if (readImportFiles) {
- processImports();
- }
- ts.processCommentPragmas(pragmaContext, sourceText);
- ts.processPragmasIntoFields(pragmaContext, ts.noop);
- if (externalModule) {
- // for external modules module all nested ambient modules are augmentations
- if (ambientExternalModules) {
- // move all detected ambient modules to imported files since they need to be resolved
- for (var _i = 0, ambientExternalModules_1 = ambientExternalModules; _i < ambientExternalModules_1.length; _i++) {
- var decl = ambientExternalModules_1[_i];
- importedFiles.push(decl.ref);
- }
- }
- return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, libReferenceDirectives: pragmaContext.libReferenceDirectives, importedFiles: importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined };
- }
- else {
- // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0
- var ambientModuleNames = void 0;
- if (ambientExternalModules) {
- for (var _a = 0, ambientExternalModules_2 = ambientExternalModules; _a < ambientExternalModules_2.length; _a++) {
- var decl = ambientExternalModules_2[_a];
- if (decl.depth === 0) {
- if (!ambientModuleNames) {
- ambientModuleNames = [];
- }
- ambientModuleNames.push(decl.ref.fileName);
- }
- else {
- importedFiles.push(decl.ref);
- }
- }
- }
- return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, libReferenceDirectives: pragmaContext.libReferenceDirectives, importedFiles: importedFiles, isLibFile: !!pragmaContext.hasNoDefaultLib, ambientExternalModules: ambientModuleNames };
- }
- }
- ts.preProcessFile = preProcessFile;
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var Rename;
- (function (Rename) {
- function getRenameInfo(program, sourceFile, position, options) {
- var node = ts.getAdjustedRenameLocation(ts.getTouchingPropertyName(sourceFile, position));
- if (nodeIsEligibleForRename(node)) {
- var renameInfo = getRenameInfoForNode(node, program.getTypeChecker(), sourceFile, function (declaration) { return program.isSourceFileDefaultLibrary(declaration.getSourceFile()); }, options);
- if (renameInfo) {
- return renameInfo;
- }
- }
- return getRenameInfoError(ts.Diagnostics.You_cannot_rename_this_element);
- }
- Rename.getRenameInfo = getRenameInfo;
- function getRenameInfoForNode(node, typeChecker, sourceFile, isDefinedInLibraryFile, options) {
- var symbol = typeChecker.getSymbolAtLocation(node);
- if (!symbol)
- return;
- // Only allow a symbol to be renamed if it actually has at least one declaration.
- var declarations = symbol.declarations;
- if (!declarations || declarations.length === 0)
- return;
- // Disallow rename for elements that are defined in the standard TypeScript library.
- if (declarations.some(isDefinedInLibraryFile)) {
- return getRenameInfoError(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library);
- }
- // Cannot rename `default` as in `import { default as foo } from "./someModule";
- if (ts.isIdentifier(node) && node.originalKeywordKind === 84 /* DefaultKeyword */ && symbol.parent && symbol.parent.flags & 1536 /* Module */) {
- return undefined;
- }
- if (ts.isStringLiteralLike(node) && ts.tryGetImportFromModuleSpecifier(node)) {
- return options && options.allowRenameOfImportPath ? getRenameInfoForModule(node, sourceFile, symbol) : undefined;
- }
- var kind = ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node);
- var specifierName = (ts.isImportOrExportSpecifierName(node) || ts.isStringOrNumericLiteralLike(node) && node.parent.kind === 154 /* ComputedPropertyName */)
- ? ts.stripQuotes(ts.getTextOfIdentifierOrLiteral(node))
- : undefined;
- var displayName = specifierName || typeChecker.symbolToString(symbol);
- var fullDisplayName = specifierName || typeChecker.getFullyQualifiedName(symbol);
- return getRenameInfoSuccess(displayName, fullDisplayName, kind, ts.SymbolDisplay.getSymbolModifiers(symbol), node, sourceFile);
- }
- function getRenameInfoForModule(node, sourceFile, moduleSymbol) {
- if (!ts.isExternalModuleNameRelative(node.text)) {
- return getRenameInfoError(ts.Diagnostics.You_cannot_rename_a_module_via_a_global_import);
- }
- var moduleSourceFile = ts.find(moduleSymbol.declarations, ts.isSourceFile);
- if (!moduleSourceFile)
- return undefined;
- var withoutIndex = ts.endsWith(node.text, "/index") || ts.endsWith(node.text, "/index.js") ? undefined : ts.tryRemoveSuffix(ts.removeFileExtension(moduleSourceFile.fileName), "/index");
- var name = withoutIndex === undefined ? moduleSourceFile.fileName : withoutIndex;
- var kind = withoutIndex === undefined ? "module" /* moduleElement */ : "directory" /* directory */;
- var indexAfterLastSlash = node.text.lastIndexOf("/") + 1;
- // Span should only be the last component of the path. + 1 to account for the quote character.
- var triggerSpan = ts.createTextSpan(node.getStart(sourceFile) + 1 + indexAfterLastSlash, node.text.length - indexAfterLastSlash);
- return {
- canRename: true,
- fileToRename: name,
- kind: kind,
- displayName: name,
- fullDisplayName: name,
- kindModifiers: "" /* none */,
- triggerSpan: triggerSpan,
- };
- }
- function getRenameInfoSuccess(displayName, fullDisplayName, kind, kindModifiers, node, sourceFile) {
- return {
- canRename: true,
- fileToRename: undefined,
- kind: kind,
- displayName: displayName,
- fullDisplayName: fullDisplayName,
- kindModifiers: kindModifiers,
- triggerSpan: createTriggerSpanForNode(node, sourceFile)
- };
- }
- function getRenameInfoError(diagnostic) {
- return { canRename: false, localizedErrorMessage: ts.getLocaleSpecificMessage(diagnostic) };
- }
- function createTriggerSpanForNode(node, sourceFile) {
- var start = node.getStart(sourceFile);
- var width = node.getWidth(sourceFile);
- if (ts.isStringLiteralLike(node)) {
- // Exclude the quotes
- start += 1;
- width -= 2;
- }
- return ts.createTextSpan(start, width);
- }
- function nodeIsEligibleForRename(node) {
- switch (node.kind) {
- case 75 /* Identifier */:
- case 76 /* PrivateIdentifier */:
- case 10 /* StringLiteral */:
- case 14 /* NoSubstitutionTemplateLiteral */:
- case 104 /* ThisKeyword */:
- return true;
- case 8 /* NumericLiteral */:
- return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node);
- default:
- return false;
- }
- }
- })(Rename = ts.Rename || (ts.Rename = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var SmartSelectionRange;
- (function (SmartSelectionRange) {
- function getSmartSelectionRange(pos, sourceFile) {
- var selectionRange = {
- textSpan: ts.createTextSpanFromBounds(sourceFile.getFullStart(), sourceFile.getEnd())
- };
- var parentNode = sourceFile;
- outer: while (true) {
- var children = getSelectionChildren(parentNode);
- if (!children.length)
- break;
- for (var i = 0; i < children.length; i++) {
- var prevNode = children[i - 1];
- var node = children[i];
- var nextNode = children[i + 1];
- if (node.getStart(sourceFile) > pos) {
- break outer;
- }
- if (positionShouldSnapToNode(sourceFile, pos, node)) {
- // 1. Blocks are effectively redundant with SyntaxLists.
- // 2. TemplateSpans, along with the SyntaxLists containing them, are a somewhat unintuitive grouping
- // of things that should be considered independently.
- // 3. A VariableStatement’s children are just a VaraiableDeclarationList and a semicolon.
- // 4. A lone VariableDeclaration in a VaraibleDeclaration feels redundant with the VariableStatement.
- //
- // Dive in without pushing a selection range.
- if (ts.isBlock(node)
- || ts.isTemplateSpan(node) || ts.isTemplateHead(node) || ts.isTemplateTail(node)
- || prevNode && ts.isTemplateHead(prevNode)
- || ts.isVariableDeclarationList(node) && ts.isVariableStatement(parentNode)
- || ts.isSyntaxList(node) && ts.isVariableDeclarationList(parentNode)
- || ts.isVariableDeclaration(node) && ts.isSyntaxList(parentNode) && children.length === 1) {
- parentNode = node;
- break;
- }
- // Synthesize a stop for '${ ... }' since '${' and '}' actually belong to siblings.
- if (ts.isTemplateSpan(parentNode) && nextNode && ts.isTemplateMiddleOrTemplateTail(nextNode)) {
- var start_2 = node.getFullStart() - "${".length;
- var end_2 = nextNode.getStart() + "}".length;
- pushSelectionRange(start_2, end_2);
- }
- // Blocks with braces, brackets, parens, or JSX tags on separate lines should be
- // selected from open to close, including whitespace but not including the braces/etc. themselves.
- var isBetweenMultiLineBookends = ts.isSyntaxList(node)
- && isListOpener(prevNode)
- && isListCloser(nextNode)
- && !ts.positionsAreOnSameLine(prevNode.getStart(), nextNode.getStart(), sourceFile);
- var jsDocCommentStart = ts.hasJSDocNodes(node) && node.jsDoc[0].getStart();
- var start = isBetweenMultiLineBookends ? prevNode.getEnd() : node.getStart();
- var end = isBetweenMultiLineBookends ? nextNode.getStart() : node.getEnd();
- if (ts.isNumber(jsDocCommentStart)) {
- pushSelectionRange(jsDocCommentStart, end);
- }
- pushSelectionRange(start, end);
- // String literals should have a stop both inside and outside their quotes.
- if (ts.isStringLiteral(node) || ts.isTemplateLiteral(node)) {
- pushSelectionRange(start + 1, end - 1);
- }
- parentNode = node;
- break;
- }
- // If we made it to the end of the for loop, we’re done.
- // In practice, I’ve only seen this happen at the very end
- // of a SourceFile.
- if (i === children.length - 1) {
- break outer;
- }
- }
- }
- return selectionRange;
- function pushSelectionRange(start, end) {
- // Skip empty ranges
- if (start !== end) {
- var textSpan = ts.createTextSpanFromBounds(start, end);
- if (!selectionRange || (
- // Skip ranges that are identical to the parent
- !ts.textSpansEqual(textSpan, selectionRange.textSpan) &&
- // Skip ranges that don’t contain the original position
- ts.textSpanIntersectsWithPosition(textSpan, pos))) {
- selectionRange = __assign({ textSpan: textSpan }, selectionRange && { parent: selectionRange });
- }
- }
- }
- }
- SmartSelectionRange.getSmartSelectionRange = getSmartSelectionRange;
- /**
- * Like `ts.positionBelongsToNode`, except positions immediately after nodes
- * count too, unless that position belongs to the next node. In effect, makes
- * selections able to snap to preceding tokens when the cursor is on the tail
- * end of them with only whitespace ahead.
- * @param sourceFile The source file containing the nodes.
- * @param pos The position to check.
- * @param node The candidate node to snap to.
- */
- function positionShouldSnapToNode(sourceFile, pos, node) {
- // Can’t use 'ts.positionBelongsToNode()' here because it cleverly accounts
- // for missing nodes, which can’t really be considered when deciding what
- // to select.
- ts.Debug.assert(node.pos <= pos);
- if (pos < node.end) {
- return true;
- }
- var nodeEnd = node.getEnd();
- if (nodeEnd === pos) {
- return ts.getTouchingPropertyName(sourceFile, pos).pos < node.end;
- }
- return false;
- }
- var isImport = ts.or(ts.isImportDeclaration, ts.isImportEqualsDeclaration);
- /**
- * Gets the children of a node to be considered for selection ranging,
- * transforming them into an artificial tree according to their intuitive
- * grouping where no grouping actually exists in the parse tree. For example,
- * top-level imports are grouped into their own SyntaxList so they can be
- * selected all together, even though in the AST they’re just siblings of each
- * other as well as of other top-level statements and declarations.
- */
- function getSelectionChildren(node) {
- // Group top-level imports
- if (ts.isSourceFile(node)) {
- return groupChildren(node.getChildAt(0).getChildren(), isImport);
- }
- // Mapped types _look_ like ObjectTypes with a single member,
- // but in fact don’t contain a SyntaxList or a node containing
- // the “key/value” pair like ObjectTypes do, but it seems intuitive
- // that the selection would snap to those points. The philosophy
- // of choosing a selection range is not so much about what the
- // syntax currently _is_ as what the syntax might easily become
- // if the user is making a selection; e.g., we synthesize a selection
- // around the “key/value” pair not because there’s a node there, but
- // because it allows the mapped type to become an object type with a
- // few keystrokes.
- if (ts.isMappedTypeNode(node)) {
- var _a = node.getChildren(), openBraceToken = _a[0], children = _a.slice(1);
- var closeBraceToken = ts.Debug.checkDefined(children.pop());
- ts.Debug.assertEqual(openBraceToken.kind, 18 /* OpenBraceToken */);
- ts.Debug.assertEqual(closeBraceToken.kind, 19 /* CloseBraceToken */);
- // Group `-/+readonly` and `-/+?`
- var groupedWithPlusMinusTokens = groupChildren(children, function (child) {
- return child === node.readonlyToken || child.kind === 138 /* ReadonlyKeyword */ ||
- child === node.questionToken || child.kind === 57 /* QuestionToken */;
- });
- // Group type parameter with surrounding brackets
- var groupedWithBrackets = groupChildren(groupedWithPlusMinusTokens, function (_a) {
- var kind = _a.kind;
- return kind === 22 /* OpenBracketToken */ ||
- kind === 155 /* TypeParameter */ ||
- kind === 23 /* CloseBracketToken */;
- });
- return [
- openBraceToken,
- // Pivot on `:`
- createSyntaxList(splitChildren(groupedWithBrackets, function (_a) {
- var kind = _a.kind;
- return kind === 58 /* ColonToken */;
- })),
- closeBraceToken,
- ];
- }
- // Group modifiers and property name, then pivot on `:`.
- if (ts.isPropertySignature(node)) {
- var children = groupChildren(node.getChildren(), function (child) {
- return child === node.name || ts.contains(node.modifiers, child);
- });
- return splitChildren(children, function (_a) {
- var kind = _a.kind;
- return kind === 58 /* ColonToken */;
- });
- }
- // Group the parameter name with its `...`, then that group with its `?`, then pivot on `=`.
- if (ts.isParameter(node)) {
- var groupedDotDotDotAndName_1 = groupChildren(node.getChildren(), function (child) {
- return child === node.dotDotDotToken || child === node.name;
- });
- var groupedWithQuestionToken = groupChildren(groupedDotDotDotAndName_1, function (child) {
- return child === groupedDotDotDotAndName_1[0] || child === node.questionToken;
- });
- return splitChildren(groupedWithQuestionToken, function (_a) {
- var kind = _a.kind;
- return kind === 62 /* EqualsToken */;
- });
- }
- // Pivot on '='
- if (ts.isBindingElement(node)) {
- return splitChildren(node.getChildren(), function (_a) {
- var kind = _a.kind;
- return kind === 62 /* EqualsToken */;
- });
- }
- return node.getChildren();
- }
- /**
- * Groups sibling nodes together into their own SyntaxList if they
- * a) are adjacent, AND b) match a predicate function.
- */
- function groupChildren(children, groupOn) {
- var result = [];
- var group;
- for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
- var child = children_1[_i];
- if (groupOn(child)) {
- group = group || [];
- group.push(child);
- }
- else {
- if (group) {
- result.push(createSyntaxList(group));
- group = undefined;
- }
- result.push(child);
- }
- }
- if (group) {
- result.push(createSyntaxList(group));
- }
- return result;
- }
- /**
- * Splits sibling nodes into up to four partitions:
- * 1) everything left of the first node matched by `pivotOn`,
- * 2) the first node matched by `pivotOn`,
- * 3) everything right of the first node matched by `pivotOn`,
- * 4) a trailing semicolon, if `separateTrailingSemicolon` is enabled.
- * The left and right groups, if not empty, will each be grouped into their own containing SyntaxList.
- * @param children The sibling nodes to split.
- * @param pivotOn The predicate function to match the node to be the pivot. The first node that matches
- * the predicate will be used; any others that may match will be included into the right-hand group.
- * @param separateTrailingSemicolon If the last token is a semicolon, it will be returned as a separate
- * child rather than be included in the right-hand group.
- */
- function splitChildren(children, pivotOn, separateTrailingSemicolon) {
- if (separateTrailingSemicolon === void 0) { separateTrailingSemicolon = true; }
- if (children.length < 2) {
- return children;
- }
- var splitTokenIndex = ts.findIndex(children, pivotOn);
- if (splitTokenIndex === -1) {
- return children;
- }
- var leftChildren = children.slice(0, splitTokenIndex);
- var splitToken = children[splitTokenIndex];
- var lastToken = ts.last(children);
- var separateLastToken = separateTrailingSemicolon && lastToken.kind === 26 /* SemicolonToken */;
- var rightChildren = children.slice(splitTokenIndex + 1, separateLastToken ? children.length - 1 : undefined);
- var result = ts.compact([
- leftChildren.length ? createSyntaxList(leftChildren) : undefined,
- splitToken,
- rightChildren.length ? createSyntaxList(rightChildren) : undefined,
- ]);
- return separateLastToken ? result.concat(lastToken) : result;
- }
- function createSyntaxList(children) {
- ts.Debug.assertGreaterThanOrEqual(children.length, 1);
- var syntaxList = ts.createNode(324 /* SyntaxList */, children[0].pos, ts.last(children).end);
- syntaxList._children = children;
- return syntaxList;
- }
- function isListOpener(token) {
- var kind = token && token.kind;
- return kind === 18 /* OpenBraceToken */
- || kind === 22 /* OpenBracketToken */
- || kind === 20 /* OpenParenToken */
- || kind === 268 /* JsxOpeningElement */;
- }
- function isListCloser(token) {
- var kind = token && token.kind;
- return kind === 19 /* CloseBraceToken */
- || kind === 23 /* CloseBracketToken */
- || kind === 21 /* CloseParenToken */
- || kind === 269 /* JsxClosingElement */;
- }
- })(SmartSelectionRange = ts.SmartSelectionRange || (ts.SmartSelectionRange = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var SignatureHelp;
- (function (SignatureHelp) {
- var InvocationKind;
- (function (InvocationKind) {
- InvocationKind[InvocationKind["Call"] = 0] = "Call";
- InvocationKind[InvocationKind["TypeArgs"] = 1] = "TypeArgs";
- InvocationKind[InvocationKind["Contextual"] = 2] = "Contextual";
- })(InvocationKind || (InvocationKind = {}));
- function getSignatureHelpItems(program, sourceFile, position, triggerReason, cancellationToken) {
- var typeChecker = program.getTypeChecker();
- // Decide whether to show signature help
- var startingToken = ts.findTokenOnLeftOfPosition(sourceFile, position);
- if (!startingToken) {
- // We are at the beginning of the file
- return undefined;
- }
- // Only need to be careful if the user typed a character and signature help wasn't showing.
- var onlyUseSyntacticOwners = !!triggerReason && triggerReason.kind === "characterTyped";
- // Bail out quickly in the middle of a string or comment, don't provide signature help unless the user explicitly requested it.
- if (onlyUseSyntacticOwners && (ts.isInString(sourceFile, position, startingToken) || ts.isInComment(sourceFile, position))) {
- return undefined;
- }
- var isManuallyInvoked = !!triggerReason && triggerReason.kind === "invoked";
- var argumentInfo = getContainingArgumentInfo(startingToken, position, sourceFile, typeChecker, isManuallyInvoked);
- if (!argumentInfo)
- return undefined;
- cancellationToken.throwIfCancellationRequested();
- // Extra syntactic and semantic filtering of signature help
- var candidateInfo = getCandidateOrTypeInfo(argumentInfo, typeChecker, sourceFile, startingToken, onlyUseSyntacticOwners);
- cancellationToken.throwIfCancellationRequested();
- if (!candidateInfo) {
- // We didn't have any sig help items produced by the TS compiler. If this is a JS
- // file, then see if we can figure out anything better.
- return ts.isSourceFileJS(sourceFile) ? createJSSignatureHelpItems(argumentInfo, program, cancellationToken) : undefined;
- }
- return typeChecker.runWithCancellationToken(cancellationToken, function (typeChecker) {
- return candidateInfo.kind === 0 /* Candidate */
- ? createSignatureHelpItems(candidateInfo.candidates, candidateInfo.resolvedSignature, argumentInfo, sourceFile, typeChecker)
- : createTypeHelpItems(candidateInfo.symbol, argumentInfo, sourceFile, typeChecker);
- });
- }
- SignatureHelp.getSignatureHelpItems = getSignatureHelpItems;
- var CandidateOrTypeKind;
- (function (CandidateOrTypeKind) {
- CandidateOrTypeKind[CandidateOrTypeKind["Candidate"] = 0] = "Candidate";
- CandidateOrTypeKind[CandidateOrTypeKind["Type"] = 1] = "Type";
- })(CandidateOrTypeKind || (CandidateOrTypeKind = {}));
- function getCandidateOrTypeInfo(_a, checker, sourceFile, startingToken, onlyUseSyntacticOwners) {
- var invocation = _a.invocation, argumentCount = _a.argumentCount;
- switch (invocation.kind) {
- case 0 /* Call */: {
- if (onlyUseSyntacticOwners && !isSyntacticOwner(startingToken, invocation.node, sourceFile)) {
- return undefined;
- }
- var candidates = [];
- var resolvedSignature = checker.getResolvedSignatureForSignatureHelp(invocation.node, candidates, argumentCount); // TODO: GH#18217
- return candidates.length === 0 ? undefined : { kind: 0 /* Candidate */, candidates: candidates, resolvedSignature: resolvedSignature };
- }
- case 1 /* TypeArgs */: {
- var called = invocation.called;
- if (onlyUseSyntacticOwners && !containsPrecedingToken(startingToken, sourceFile, ts.isIdentifier(called) ? called.parent : called)) {
- return undefined;
- }
- var candidates = ts.getPossibleGenericSignatures(called, argumentCount, checker);
- if (candidates.length !== 0)
- return { kind: 0 /* Candidate */, candidates: candidates, resolvedSignature: ts.first(candidates) };
- var symbol = checker.getSymbolAtLocation(called);
- return symbol && { kind: 1 /* Type */, symbol: symbol };
- }
- case 2 /* Contextual */:
- return { kind: 0 /* Candidate */, candidates: [invocation.signature], resolvedSignature: invocation.signature };
- default:
- return ts.Debug.assertNever(invocation);
- }
- }
- function isSyntacticOwner(startingToken, node, sourceFile) {
- if (!ts.isCallOrNewExpression(node))
- return false;
- var invocationChildren = node.getChildren(sourceFile);
- switch (startingToken.kind) {
- case 20 /* OpenParenToken */:
- return ts.contains(invocationChildren, startingToken);
- case 27 /* CommaToken */: {
- var containingList = ts.findContainingList(startingToken);
- return !!containingList && ts.contains(invocationChildren, containingList);
- }
- case 29 /* LessThanToken */:
- return containsPrecedingToken(startingToken, sourceFile, node.expression);
- default:
- return false;
- }
- }
- function createJSSignatureHelpItems(argumentInfo, program, cancellationToken) {
- if (argumentInfo.invocation.kind === 2 /* Contextual */)
- return undefined;
- // See if we can find some symbol with the call expression name that has call signatures.
- var expression = getExpressionFromInvocation(argumentInfo.invocation);
- var name = ts.isIdentifier(expression) ? expression.text : ts.isPropertyAccessExpression(expression) ? expression.name.text : undefined;
- var typeChecker = program.getTypeChecker();
- return name === undefined ? undefined : ts.firstDefined(program.getSourceFiles(), function (sourceFile) {
- return ts.firstDefined(sourceFile.getNamedDeclarations().get(name), function (declaration) {
- var type = declaration.symbol && typeChecker.getTypeOfSymbolAtLocation(declaration.symbol, declaration);
- var callSignatures = type && type.getCallSignatures();
- if (callSignatures && callSignatures.length) {
- return typeChecker.runWithCancellationToken(cancellationToken, function (typeChecker) { return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo, sourceFile, typeChecker); });
- }
- });
- });
- }
- function containsPrecedingToken(startingToken, sourceFile, container) {
- var pos = startingToken.getFullStart();
- // There’s a possibility that `startingToken.parent` contains only `startingToken` and
- // missing nodes, none of which are valid to be returned by `findPrecedingToken`. In that
- // case, the preceding token we want is actually higher up the tree—almost definitely the
- // next parent, but theoretically the situation with missing nodes might be happening on
- // multiple nested levels.
- var currentParent = startingToken.parent;
- while (currentParent) {
- var precedingToken = ts.findPrecedingToken(pos, sourceFile, currentParent, /*excludeJsdoc*/ true);
- if (precedingToken) {
- return ts.rangeContainsRange(container, precedingToken);
- }
- currentParent = currentParent.parent;
- }
- return ts.Debug.fail("Could not find preceding token");
- }
- function getArgumentInfoForCompletions(node, position, sourceFile) {
- var info = getImmediatelyContainingArgumentInfo(node, position, sourceFile);
- return !info || info.isTypeParameterList || info.invocation.kind !== 0 /* Call */ ? undefined
- : { invocation: info.invocation.node, argumentCount: info.argumentCount, argumentIndex: info.argumentIndex };
- }
- SignatureHelp.getArgumentInfoForCompletions = getArgumentInfoForCompletions;
- function getArgumentOrParameterListInfo(node, sourceFile) {
- var info = getArgumentOrParameterListAndIndex(node, sourceFile);
- if (!info)
- return undefined;
- var list = info.list, argumentIndex = info.argumentIndex;
- var argumentCount = getArgumentCount(list);
- if (argumentIndex !== 0) {
- ts.Debug.assertLessThan(argumentIndex, argumentCount);
- }
- var argumentsSpan = getApplicableSpanForArguments(list, sourceFile);
- return { list: list, argumentIndex: argumentIndex, argumentCount: argumentCount, argumentsSpan: argumentsSpan };
- }
- function getArgumentOrParameterListAndIndex(node, sourceFile) {
- if (node.kind === 29 /* LessThanToken */ || node.kind === 20 /* OpenParenToken */) {
- // Find the list that starts right *after* the < or ( token.
- // If the user has just opened a list, consider this item 0.
- return { list: getChildListThatStartsWithOpenerToken(node.parent, node, sourceFile), argumentIndex: 0 };
- }
- else {
- // findListItemInfo can return undefined if we are not in parent's argument list
- // or type argument list. This includes cases where the cursor is:
- // - To the right of the closing parenthesis, non-substitution template, or template tail.
- // - Between the type arguments and the arguments (greater than token)
- // - On the target of the call (parent.func)
- // - On the 'new' keyword in a 'new' expression
- var list = ts.findContainingList(node);
- return list && { list: list, argumentIndex: getArgumentIndex(list, node) };
- }
- }
- /**
- * Returns relevant information for the argument list and the current argument if we are
- * in the argument of an invocation; returns undefined otherwise.
- */
- function getImmediatelyContainingArgumentInfo(node, position, sourceFile) {
- var parent = node.parent;
- if (ts.isCallOrNewExpression(parent)) {
- var invocation = parent;
- // There are 3 cases to handle:
- // 1. The token introduces a list, and should begin a signature help session
- // 2. The token is either not associated with a list, or ends a list, so the session should end
- // 3. The token is buried inside a list, and should give signature help
- //
- // The following are examples of each:
- //
- // Case 1:
- // foo<#T, U>(#a, b) -> The token introduces a list, and should begin a signature help session
- // Case 2:
- // fo#o#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end
- // Case 3:
- // foo(a#, #b#) -> The token is buried inside a list, and should give signature help
- // Find out if 'node' is an argument, a type argument, or neither
- var info = getArgumentOrParameterListInfo(node, sourceFile);
- if (!info)
- return undefined;
- var list = info.list, argumentIndex = info.argumentIndex, argumentCount = info.argumentCount, argumentsSpan = info.argumentsSpan;
- var isTypeParameterList = !!parent.typeArguments && parent.typeArguments.pos === list.pos;
- return { isTypeParameterList: isTypeParameterList, invocation: { kind: 0 /* Call */, node: invocation }, argumentsSpan: argumentsSpan, argumentIndex: argumentIndex, argumentCount: argumentCount };
- }
- else if (ts.isNoSubstitutionTemplateLiteral(node) && ts.isTaggedTemplateExpression(parent)) {
- // Check if we're actually inside the template;
- // otherwise we'll fall out and return undefined.
- if (ts.isInsideTemplateLiteral(node, position, sourceFile)) {
- return getArgumentListInfoForTemplate(parent, /*argumentIndex*/ 0, sourceFile);
- }
- return undefined;
- }
- else if (ts.isTemplateHead(node) && parent.parent.kind === 198 /* TaggedTemplateExpression */) {
- var templateExpression = parent;
- var tagExpression = templateExpression.parent;
- ts.Debug.assert(templateExpression.kind === 211 /* TemplateExpression */);
- var argumentIndex = ts.isInsideTemplateLiteral(node, position, sourceFile) ? 0 : 1;
- return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile);
- }
- else if (ts.isTemplateSpan(parent) && ts.isTaggedTemplateExpression(parent.parent.parent)) {
- var templateSpan = parent;
- var tagExpression = parent.parent.parent;
- // If we're just after a template tail, don't show signature help.
- if (ts.isTemplateTail(node) && !ts.isInsideTemplateLiteral(node, position, sourceFile)) {
- return undefined;
- }
- var spanIndex = templateSpan.parent.templateSpans.indexOf(templateSpan);
- var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node, position, sourceFile);
- return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile);
- }
- else if (ts.isJsxOpeningLikeElement(parent)) {
- // Provide a signature help for JSX opening element or JSX self-closing element.
- // This is not guarantee that JSX tag-name is resolved into stateless function component. (that is done in "getSignatureHelpItems")
- // i.e
- // export function MainButton(props: ButtonProps, context: any): JSX.Element { ... }
- // ' 'b'. So, in this case the arg count will be 2. However, there
- // is a small subtlety. If you have "Foo(a,)", then the child list will just have
- // 'a' ''. So, in the case where the last child is a comma, we increase the
- // arg count by one to compensate.
- //
- // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
- // we'll have: 'a' '' ''
- // That will give us 2 non-commas. We then add one for the last comma, giving us an
- // arg count of 3.
- var listChildren = argumentsList.getChildren();
- var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 27 /* CommaToken */; });
- if (listChildren.length > 0 && ts.last(listChildren).kind === 27 /* CommaToken */) {
- argumentCount++;
- }
- return argumentCount;
- }
- // spanIndex is either the index for a given template span.
- // This does not give appropriate results for a NoSubstitutionTemplateLiteral
- function getArgumentIndexForTemplatePiece(spanIndex, node, position, sourceFile) {
- // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1.
- // There are three cases we can encounter:
- // 1. We are precisely in the template literal (argIndex = 0).
- // 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1).
- // 3. We are directly to the right of the template literal, but because we look for the token on the left,
- // not enough to put us in the substitution expression; we should consider ourselves part of
- // the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1).
- //
- /* eslint-disable no-double-space */
- // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # `
- // ^ ^ ^ ^ ^ ^ ^ ^ ^
- // Case: 1 1 3 2 1 3 2 2 1
- /* eslint-enable no-double-space */
- ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
- if (ts.isTemplateLiteralToken(node)) {
- if (ts.isInsideTemplateLiteral(node, position, sourceFile)) {
- return 0;
- }
- return spanIndex + 2;
- }
- return spanIndex + 1;
- }
- function getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile) {
- // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
- var argumentCount = ts.isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 : tagExpression.template.templateSpans.length + 1;
- if (argumentIndex !== 0) {
- ts.Debug.assertLessThan(argumentIndex, argumentCount);
- }
- return {
- isTypeParameterList: false,
- invocation: { kind: 0 /* Call */, node: tagExpression },
- argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile),
- argumentIndex: argumentIndex,
- argumentCount: argumentCount
- };
- }
- function getApplicableSpanForArguments(argumentsList, sourceFile) {
- // We use full start and skip trivia on the end because we want to include trivia on
- // both sides. For example,
- //
- // foo( /*comment */ a, b, c /*comment*/ )
- // | |
- //
- // The applicable span is from the first bar to the second bar (inclusive,
- // but not including parentheses)
- var applicableSpanStart = argumentsList.getFullStart();
- var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false);
- return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
- }
- function getApplicableSpanForTaggedTemplate(taggedTemplate, sourceFile) {
- var template = taggedTemplate.template;
- var applicableSpanStart = template.getStart();
- var applicableSpanEnd = template.getEnd();
- // We need to adjust the end position for the case where the template does not have a tail.
- // Otherwise, we will not show signature help past the expression.
- // For example,
- //
- // ` ${ 1 + 1 foo(10)
- // | |
- // This is because a Missing node has no width. However, what we actually want is to include trivia
- // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
- if (template.kind === 211 /* TemplateExpression */) {
- var lastSpan = ts.last(template.templateSpans);
- if (lastSpan.literal.getFullWidth() === 0) {
- applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
- }
- }
- return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
- }
- function getContainingArgumentInfo(node, position, sourceFile, checker, isManuallyInvoked) {
- var _loop_7 = function (n) {
- // If the node is not a subspan of its parent, this is a big problem.
- // There have been crashes that might be caused by this violation.
- ts.Debug.assert(ts.rangeContainsRange(n.parent, n), "Not a subspan", function () { return "Child: " + ts.Debug.formatSyntaxKind(n.kind) + ", parent: " + ts.Debug.formatSyntaxKind(n.parent.kind); });
- var argumentInfo = getImmediatelyContainingArgumentOrContextualParameterInfo(n, position, sourceFile, checker);
- if (argumentInfo) {
- return { value: argumentInfo };
- }
- };
- for (var n = node; !ts.isSourceFile(n) && (isManuallyInvoked || !ts.isBlock(n)); n = n.parent) {
- var state_2 = _loop_7(n);
- if (typeof state_2 === "object")
- return state_2.value;
- }
- return undefined;
- }
- function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) {
- var children = parent.getChildren(sourceFile);
- var indexOfOpenerToken = children.indexOf(openerToken);
- ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
- return children[indexOfOpenerToken + 1];
- }
- function getExpressionFromInvocation(invocation) {
- return invocation.kind === 0 /* Call */ ? ts.getInvokedExpression(invocation.node) : invocation.called;
- }
- function getEnclosingDeclarationFromInvocation(invocation) {
- return invocation.kind === 0 /* Call */ ? invocation.node : invocation.kind === 1 /* TypeArgs */ ? invocation.called : invocation.node;
- }
- var signatureHelpNodeBuilderFlags = 8192 /* OmitParameterModifiers */ | 70221824 /* IgnoreErrors */ | 16384 /* UseAliasDefinedOutsideCurrentScope */;
- function createSignatureHelpItems(candidates, resolvedSignature, _a, sourceFile, typeChecker) {
- var isTypeParameterList = _a.isTypeParameterList, argumentCount = _a.argumentCount, applicableSpan = _a.argumentsSpan, invocation = _a.invocation, argumentIndex = _a.argumentIndex;
- var enclosingDeclaration = getEnclosingDeclarationFromInvocation(invocation);
- var callTargetSymbol = invocation.kind === 2 /* Contextual */ ? invocation.symbol : typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation));
- var callTargetDisplayParts = callTargetSymbol ? ts.symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : ts.emptyArray;
- var items = candidates.map(function (candidateSignature) { return getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, typeChecker, enclosingDeclaration, sourceFile); });
- if (argumentIndex !== 0) {
- ts.Debug.assertLessThan(argumentIndex, argumentCount);
- }
- var selectedItemIndex = candidates.indexOf(resolvedSignature);
- ts.Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function.
- return { items: items, applicableSpan: applicableSpan, selectedItemIndex: selectedItemIndex, argumentIndex: argumentIndex, argumentCount: argumentCount };
- }
- function createTypeHelpItems(symbol, _a, sourceFile, checker) {
- var argumentCount = _a.argumentCount, applicableSpan = _a.argumentsSpan, invocation = _a.invocation, argumentIndex = _a.argumentIndex;
- var typeParameters = checker.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
- if (!typeParameters)
- return undefined;
- var items = [getTypeHelpItem(symbol, typeParameters, checker, getEnclosingDeclarationFromInvocation(invocation), sourceFile)];
- return { items: items, applicableSpan: applicableSpan, selectedItemIndex: 0, argumentIndex: argumentIndex, argumentCount: argumentCount };
- }
- function getTypeHelpItem(symbol, typeParameters, checker, enclosingDeclaration, sourceFile) {
- var typeSymbolDisplay = ts.symbolToDisplayParts(checker, symbol);
- var printer = ts.createPrinter({ removeComments: true });
- var parameters = typeParameters.map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); });
- var documentation = symbol.getDocumentationComment(checker);
- var tags = symbol.getJsDocTags();
- var prefixDisplayParts = __spreadArrays(typeSymbolDisplay, [ts.punctuationPart(29 /* LessThanToken */)]);
- return { isVariadic: false, prefixDisplayParts: prefixDisplayParts, suffixDisplayParts: [ts.punctuationPart(31 /* GreaterThanToken */)], separatorDisplayParts: separatorDisplayParts, parameters: parameters, documentation: documentation, tags: tags };
- }
- var separatorDisplayParts = [ts.punctuationPart(27 /* CommaToken */), ts.spacePart()];
- function getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, checker, enclosingDeclaration, sourceFile) {
- var _a = (isTypeParameterList ? itemInfoForTypeParameters : itemInfoForParameters)(candidateSignature, checker, enclosingDeclaration, sourceFile), isVariadic = _a.isVariadic, parameters = _a.parameters, prefix = _a.prefix, suffix = _a.suffix;
- var prefixDisplayParts = __spreadArrays(callTargetDisplayParts, prefix);
- var suffixDisplayParts = __spreadArrays(suffix, returnTypeToDisplayParts(candidateSignature, enclosingDeclaration, checker));
- var documentation = candidateSignature.getDocumentationComment(checker);
- var tags = candidateSignature.getJsDocTags();
- return { isVariadic: isVariadic, prefixDisplayParts: prefixDisplayParts, suffixDisplayParts: suffixDisplayParts, separatorDisplayParts: separatorDisplayParts, parameters: parameters, documentation: documentation, tags: tags };
- }
- function returnTypeToDisplayParts(candidateSignature, enclosingDeclaration, checker) {
- return ts.mapToDisplayParts(function (writer) {
- writer.writePunctuation(":");
- writer.writeSpace(" ");
- var predicate = checker.getTypePredicateOfSignature(candidateSignature);
- if (predicate) {
- checker.writeTypePredicate(predicate, enclosingDeclaration, /*flags*/ undefined, writer);
- }
- else {
- checker.writeType(checker.getReturnTypeOfSignature(candidateSignature), enclosingDeclaration, /*flags*/ undefined, writer);
- }
- });
- }
- function itemInfoForTypeParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) {
- var typeParameters = (candidateSignature.target || candidateSignature).typeParameters;
- var printer = ts.createPrinter({ removeComments: true });
- var parameters = (typeParameters || ts.emptyArray).map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); });
- var parameterParts = ts.mapToDisplayParts(function (writer) {
- var thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)] : [];
- var params = ts.createNodeArray(__spreadArrays(thisParameter, checker.getExpandedParameters(candidateSignature).map(function (param) { return checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags); })));
- printer.writeList(2576 /* CallExpressionArguments */, params, sourceFile, writer);
- });
- return { isVariadic: false, parameters: parameters, prefix: [ts.punctuationPart(29 /* LessThanToken */)], suffix: __spreadArrays([ts.punctuationPart(31 /* GreaterThanToken */)], parameterParts) };
- }
- function itemInfoForParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) {
- var isVariadic = checker.hasEffectiveRestParameter(candidateSignature);
- var printer = ts.createPrinter({ removeComments: true });
- var typeParameterParts = ts.mapToDisplayParts(function (writer) {
- if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
- var args = ts.createNodeArray(candidateSignature.typeParameters.map(function (p) { return checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags); }));
- printer.writeList(53776 /* TypeParameters */, args, sourceFile, writer);
- }
- });
- var parameters = checker.getExpandedParameters(candidateSignature).map(function (p) { return createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer); });
- return { isVariadic: isVariadic, parameters: parameters, prefix: __spreadArrays(typeParameterParts, [ts.punctuationPart(20 /* OpenParenToken */)]), suffix: [ts.punctuationPart(21 /* CloseParenToken */)] };
- }
- function createSignatureHelpParameterForParameter(parameter, checker, enclosingDeclaration, sourceFile, printer) {
- var displayParts = ts.mapToDisplayParts(function (writer) {
- var param = checker.symbolToParameterDeclaration(parameter, enclosingDeclaration, signatureHelpNodeBuilderFlags);
- printer.writeNode(4 /* Unspecified */, param, sourceFile, writer);
- });
- var isOptional = checker.isOptionalParameter(parameter.valueDeclaration);
- return { name: parameter.name, documentation: parameter.getDocumentationComment(checker), displayParts: displayParts, isOptional: isOptional };
- }
- function createSignatureHelpParameterForTypeParameter(typeParameter, checker, enclosingDeclaration, sourceFile, printer) {
- var displayParts = ts.mapToDisplayParts(function (writer) {
- var param = checker.typeParameterToDeclaration(typeParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags);
- printer.writeNode(4 /* Unspecified */, param, sourceFile, writer);
- });
- return { name: typeParameter.symbol.name, documentation: typeParameter.symbol.getDocumentationComment(checker), displayParts: displayParts, isOptional: false };
- }
- })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/;
- function getSourceMapper(host) {
- var getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames());
- var currentDirectory = host.getCurrentDirectory();
- var sourceFileLike = ts.createMap();
- var documentPositionMappers = ts.createMap();
- return { tryGetSourcePosition: tryGetSourcePosition, tryGetGeneratedPosition: tryGetGeneratedPosition, toLineColumnOffset: toLineColumnOffset, clearCache: clearCache };
- function toPath(fileName) {
- return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- }
- function getDocumentPositionMapper(generatedFileName, sourceFileName) {
- var path = toPath(generatedFileName);
- var value = documentPositionMappers.get(path);
- if (value)
- return value;
- var mapper;
- if (host.getDocumentPositionMapper) {
- mapper = host.getDocumentPositionMapper(generatedFileName, sourceFileName);
- }
- else if (host.readFile) {
- var file = getSourceFileLike(generatedFileName);
- mapper = file && ts.getDocumentPositionMapper({ getSourceFileLike: getSourceFileLike, getCanonicalFileName: getCanonicalFileName, log: function (s) { return host.log(s); } }, generatedFileName, ts.getLineInfo(file.text, ts.getLineStarts(file)), function (f) { return !host.fileExists || host.fileExists(f) ? host.readFile(f) : undefined; });
- }
- documentPositionMappers.set(path, mapper || ts.identitySourceMapConsumer);
- return mapper || ts.identitySourceMapConsumer;
- }
- function tryGetSourcePosition(info) {
- if (!ts.isDeclarationFileName(info.fileName))
- return undefined;
- var file = getSourceFile(info.fileName);
- if (!file)
- return undefined;
- var newLoc = getDocumentPositionMapper(info.fileName).getSourcePosition(info);
- return !newLoc || newLoc === info ? undefined : tryGetSourcePosition(newLoc) || newLoc;
- }
- function tryGetGeneratedPosition(info) {
- if (ts.isDeclarationFileName(info.fileName))
- return undefined;
- var sourceFile = getSourceFile(info.fileName);
- if (!sourceFile)
- return undefined;
- var program = host.getProgram();
- // If this is source file of project reference source (instead of redirect) there is no generated position
- if (program.isSourceOfProjectReferenceRedirect(sourceFile.fileName)) {
- return undefined;
- }
- var options = program.getCompilerOptions();
- var outPath = options.outFile || options.out;
- var declarationPath = outPath ?
- ts.removeFileExtension(outPath) + ".d.ts" /* Dts */ :
- ts.getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), currentDirectory, program.getCommonSourceDirectory(), getCanonicalFileName);
- if (declarationPath === undefined)
- return undefined;
- var newLoc = getDocumentPositionMapper(declarationPath, info.fileName).getGeneratedPosition(info);
- return newLoc === info ? undefined : newLoc;
- }
- function getSourceFile(fileName) {
- var program = host.getProgram();
- if (!program)
- return undefined;
- var path = toPath(fileName);
- // file returned here could be .d.ts when asked for .ts file if projectReferences and module resolution created this source file
- var file = program.getSourceFileByPath(path);
- return file && file.resolvedPath === path ? file : undefined;
- }
- function getOrCreateSourceFileLike(fileName) {
- var path = toPath(fileName);
- var fileFromCache = sourceFileLike.get(path);
- if (fileFromCache !== undefined)
- return fileFromCache ? fileFromCache : undefined;
- if (!host.readFile || host.fileExists && !host.fileExists(path)) {
- sourceFileLike.set(path, false);
- return undefined;
- }
- // And failing that, check the disk
- var text = host.readFile(path);
- var file = text ? createSourceFileLike(text) : false;
- sourceFileLike.set(path, file);
- return file ? file : undefined;
- }
- // This can be called from source mapper in either source program or program that includes generated file
- function getSourceFileLike(fileName) {
- return !host.getSourceFileLike ?
- getSourceFile(fileName) || getOrCreateSourceFileLike(fileName) :
- host.getSourceFileLike(fileName);
- }
- function toLineColumnOffset(fileName, position) {
- var file = getSourceFileLike(fileName); // TODO: GH#18217
- return file.getLineAndCharacterOfPosition(position);
- }
- function clearCache() {
- sourceFileLike.clear();
- documentPositionMappers.clear();
- }
- }
- ts.getSourceMapper = getSourceMapper;
- function getDocumentPositionMapper(host, generatedFileName, generatedFileLineInfo, readMapFile) {
- var mapFileName = ts.tryGetSourceMappingURL(generatedFileLineInfo);
- if (mapFileName) {
- var match = base64UrlRegExp.exec(mapFileName);
- if (match) {
- if (match[1]) {
- var base64Object = match[1];
- return convertDocumentToSourceMapper(host, ts.base64decode(ts.sys, base64Object), generatedFileName);
- }
- // Not a data URL we can parse, skip it
- mapFileName = undefined;
- }
- }
- var possibleMapLocations = [];
- if (mapFileName) {
- possibleMapLocations.push(mapFileName);
- }
- possibleMapLocations.push(generatedFileName + ".map");
- var originalMapFileName = mapFileName && ts.getNormalizedAbsolutePath(mapFileName, ts.getDirectoryPath(generatedFileName));
- for (var _i = 0, possibleMapLocations_1 = possibleMapLocations; _i < possibleMapLocations_1.length; _i++) {
- var location = possibleMapLocations_1[_i];
- var mapFileName_1 = ts.getNormalizedAbsolutePath(location, ts.getDirectoryPath(generatedFileName));
- var mapFileContents = readMapFile(mapFileName_1, originalMapFileName);
- if (ts.isString(mapFileContents)) {
- return convertDocumentToSourceMapper(host, mapFileContents, mapFileName_1);
- }
- if (mapFileContents !== undefined) {
- return mapFileContents || undefined;
- }
- }
- return undefined;
- }
- ts.getDocumentPositionMapper = getDocumentPositionMapper;
- function convertDocumentToSourceMapper(host, contents, mapFileName) {
- var map = ts.tryParseRawSourceMap(contents);
- if (!map || !map.sources || !map.file || !map.mappings) {
- // obviously invalid map
- return undefined;
- }
- // Dont support sourcemaps that contain inlined sources
- if (map.sourcesContent && map.sourcesContent.some(ts.isString))
- return undefined;
- return ts.createDocumentPositionMapper(host, map, mapFileName);
- }
- function createSourceFileLike(text, lineMap) {
- return {
- text: text,
- lineMap: lineMap,
- getLineAndCharacterOfPosition: function (pos) {
- return ts.computeLineAndCharacterOfPosition(ts.getLineStarts(this), pos);
- }
- };
- }
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var visitedNestedConvertibleFunctions = ts.createMap();
- function computeSuggestionDiagnostics(sourceFile, program, cancellationToken) {
- program.getSemanticDiagnostics(sourceFile, cancellationToken);
- var diags = [];
- var checker = program.getTypeChecker();
- if (sourceFile.commonJsModuleIndicator &&
- (ts.programContainsEs6Modules(program) || ts.compilerOptionsIndicateEs6Modules(program.getCompilerOptions())) &&
- containsTopLevelCommonjs(sourceFile)) {
- diags.push(ts.createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), ts.Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module));
- }
- var isJsFile = ts.isSourceFileJS(sourceFile);
- visitedNestedConvertibleFunctions.clear();
- check(sourceFile);
- if (ts.getAllowSyntheticDefaultImports(program.getCompilerOptions())) {
- for (var _i = 0, _a = sourceFile.imports; _i < _a.length; _i++) {
- var moduleSpecifier = _a[_i];
- var importNode = ts.importFromModuleSpecifier(moduleSpecifier);
- var name = importNameForConvertToDefaultImport(importNode);
- if (!name)
- continue;
- var module_1 = ts.getResolvedModule(sourceFile, moduleSpecifier.text);
- var resolvedFile = module_1 && program.getSourceFile(module_1.resolvedFileName);
- if (resolvedFile && resolvedFile.externalModuleIndicator && ts.isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals) {
- diags.push(ts.createDiagnosticForNode(name, ts.Diagnostics.Import_may_be_converted_to_a_default_import));
- }
- }
- }
- ts.addRange(diags, sourceFile.bindSuggestionDiagnostics);
- ts.addRange(diags, program.getSuggestionDiagnostics(sourceFile, cancellationToken));
- return diags.sort(function (d1, d2) { return d1.start - d2.start; });
- function check(node) {
- if (isJsFile) {
- if (canBeConvertedToClass(node)) {
- diags.push(ts.createDiagnosticForNode(ts.isVariableDeclaration(node.parent) ? node.parent.name : node, ts.Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration));
- }
- }
- else {
- if (ts.isVariableStatement(node) &&
- node.parent === sourceFile &&
- node.declarationList.flags & 2 /* Const */ &&
- node.declarationList.declarations.length === 1) {
- var init = node.declarationList.declarations[0].initializer;
- if (init && ts.isRequireCall(init, /*checkArgumentIsStringLiteralLike*/ true)) {
- diags.push(ts.createDiagnosticForNode(init, ts.Diagnostics.require_call_may_be_converted_to_an_import));
- }
- }
- if (ts.codefix.parameterShouldGetTypeFromJSDoc(node)) {
- diags.push(ts.createDiagnosticForNode(node.name || node, ts.Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types));
- }
- }
- if (ts.isFunctionLikeDeclaration(node)) {
- addConvertToAsyncFunctionDiagnostics(node, checker, diags);
- }
- node.forEachChild(check);
- }
- }
- ts.computeSuggestionDiagnostics = computeSuggestionDiagnostics;
- // convertToEs6Module only works on top-level, so don't trigger it if commonjs code only appears in nested scopes.
- function containsTopLevelCommonjs(sourceFile) {
- return sourceFile.statements.some(function (statement) {
- switch (statement.kind) {
- case 225 /* VariableStatement */:
- return statement.declarationList.declarations.some(function (decl) {
- return !!decl.initializer && ts.isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true);
- });
- case 226 /* ExpressionStatement */: {
- var expression = statement.expression;
- if (!ts.isBinaryExpression(expression))
- return ts.isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true);
- var kind = ts.getAssignmentDeclarationKind(expression);
- return kind === 1 /* ExportsProperty */ || kind === 2 /* ModuleExports */;
- }
- default:
- return false;
- }
- });
- }
- function propertyAccessLeftHandSide(node) {
- return ts.isPropertyAccessExpression(node) ? propertyAccessLeftHandSide(node.expression) : node;
- }
- function importNameForConvertToDefaultImport(node) {
- switch (node.kind) {
- case 254 /* ImportDeclaration */:
- var importClause = node.importClause, moduleSpecifier = node.moduleSpecifier;
- return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === 256 /* NamespaceImport */ && ts.isStringLiteral(moduleSpecifier)
- ? importClause.namedBindings.name
- : undefined;
- case 253 /* ImportEqualsDeclaration */:
- return node.name;
- default:
- return undefined;
- }
- }
- function addConvertToAsyncFunctionDiagnostics(node, checker, diags) {
- // need to check function before checking map so that deeper levels of nested callbacks are checked
- if (isConvertibleFunction(node, checker) && !visitedNestedConvertibleFunctions.has(getKeyFromNode(node))) {
- diags.push(ts.createDiagnosticForNode(!node.name && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name) ? node.parent.name : node, ts.Diagnostics.This_may_be_converted_to_an_async_function));
- }
- }
- function isConvertibleFunction(node, checker) {
- return !ts.isAsyncFunction(node) &&
- node.body &&
- ts.isBlock(node.body) &&
- hasReturnStatementWithPromiseHandler(node.body) &&
- returnsPromise(node, checker);
- }
- function returnsPromise(node, checker) {
- var functionType = checker.getTypeAtLocation(node);
- var callSignatures = checker.getSignaturesOfType(functionType, 0 /* Call */);
- var returnType = callSignatures.length ? checker.getReturnTypeOfSignature(callSignatures[0]) : undefined;
- return !!returnType && !!checker.getPromisedTypeOfPromise(returnType);
- }
- function getErrorNodeFromCommonJsIndicator(commonJsModuleIndicator) {
- return ts.isBinaryExpression(commonJsModuleIndicator) ? commonJsModuleIndicator.left : commonJsModuleIndicator;
- }
- function hasReturnStatementWithPromiseHandler(body) {
- return !!ts.forEachReturnStatement(body, isReturnStatementWithFixablePromiseHandler);
- }
- function isReturnStatementWithFixablePromiseHandler(node) {
- return ts.isReturnStatement(node) && !!node.expression && isFixablePromiseHandler(node.expression);
- }
- ts.isReturnStatementWithFixablePromiseHandler = isReturnStatementWithFixablePromiseHandler;
- // Should be kept up to date with transformExpression in convertToAsyncFunction.ts
- function isFixablePromiseHandler(node) {
- // ensure outermost call exists and is a promise handler
- if (!isPromiseHandler(node) || !node.arguments.every(isFixablePromiseArgument)) {
- return false;
- }
- // ensure all chained calls are valid
- var currentNode = node.expression;
- while (isPromiseHandler(currentNode) || ts.isPropertyAccessExpression(currentNode)) {
- if (ts.isCallExpression(currentNode) && !currentNode.arguments.every(isFixablePromiseArgument)) {
- return false;
- }
- currentNode = currentNode.expression;
- }
- return true;
- }
- ts.isFixablePromiseHandler = isFixablePromiseHandler;
- function isPromiseHandler(node) {
- return ts.isCallExpression(node) && (ts.hasPropertyAccessExpressionWithName(node, "then") && hasSupportedNumberOfArguments(node) ||
- ts.hasPropertyAccessExpressionWithName(node, "catch"));
- }
- function hasSupportedNumberOfArguments(node) {
- if (node.arguments.length > 2)
- return false;
- if (node.arguments.length < 2)
- return true;
- return ts.some(node.arguments, function (arg) {
- return arg.kind === 100 /* NullKeyword */ ||
- ts.isIdentifier(arg) && arg.text === "undefined";
- });
- }
- // should be kept up to date with getTransformationBody in convertToAsyncFunction.ts
- function isFixablePromiseArgument(arg) {
- switch (arg.kind) {
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 202 /* ArrowFunction */:
- visitedNestedConvertibleFunctions.set(getKeyFromNode(arg), true);
- // falls through
- case 100 /* NullKeyword */:
- case 75 /* Identifier */: // identifier includes undefined
- return true;
- default:
- return false;
- }
- }
- function getKeyFromNode(exp) {
- return exp.pos.toString() + ":" + exp.end.toString();
- }
- function canBeConvertedToClass(node) {
- var _a, _b, _c, _d;
- if (node.kind === 201 /* FunctionExpression */) {
- if (ts.isVariableDeclaration(node.parent) && ((_a = node.symbol.members) === null || _a === void 0 ? void 0 : _a.size)) {
- return true;
- }
- var decl = ts.getDeclarationOfExpando(node);
- var symbol = decl === null || decl === void 0 ? void 0 : decl.symbol;
- return !!(symbol && (((_b = symbol.exports) === null || _b === void 0 ? void 0 : _b.size) || ((_c = symbol.members) === null || _c === void 0 ? void 0 : _c.size)));
- }
- if (node.kind === 244 /* FunctionDeclaration */) {
- return !!((_d = node.symbol.members) === null || _d === void 0 ? void 0 : _d.size);
- }
- return false;
- }
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var SymbolDisplay;
- (function (SymbolDisplay) {
- var symbolDisplayNodeBuilderFlags = 8192 /* OmitParameterModifiers */ | 70221824 /* IgnoreErrors */ | 16384 /* UseAliasDefinedOutsideCurrentScope */;
- // TODO(drosen): use contextual SemanticMeaning.
- function getSymbolKind(typeChecker, symbol, location) {
- var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location);
- if (result !== "" /* unknown */) {
- return result;
- }
- var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol);
- if (flags & 32 /* Class */) {
- return ts.getDeclarationOfKind(symbol, 214 /* ClassExpression */) ?
- "local class" /* localClassElement */ : "class" /* classElement */;
- }
- if (flags & 384 /* Enum */)
- return "enum" /* enumElement */;
- if (flags & 524288 /* TypeAlias */)
- return "type" /* typeElement */;
- if (flags & 64 /* Interface */)
- return "interface" /* interfaceElement */;
- if (flags & 262144 /* TypeParameter */)
- return "type parameter" /* typeParameterElement */;
- if (flags & 8 /* EnumMember */)
- return "enum member" /* enumMemberElement */;
- if (flags & 2097152 /* Alias */)
- return "alias" /* alias */;
- if (flags & 1536 /* Module */)
- return "module" /* moduleElement */;
- return result;
- }
- SymbolDisplay.getSymbolKind = getSymbolKind;
- function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) {
- var roots = typeChecker.getRootSymbols(symbol);
- // If this is a method from a mapped type, leave as a method so long as it still has a call signature.
- if (roots.length === 1
- && ts.first(roots).flags & 8192 /* Method */
- // Ensure the mapped version is still a method, as opposed to `{ [K in keyof I]: number }`.
- && typeChecker.getTypeOfSymbolAtLocation(symbol, location).getNonNullableType().getCallSignatures().length !== 0) {
- return "method" /* memberFunctionElement */;
- }
- if (typeChecker.isUndefinedSymbol(symbol)) {
- return "var" /* variableElement */;
- }
- if (typeChecker.isArgumentsSymbol(symbol)) {
- return "local var" /* localVariableElement */;
- }
- if (location.kind === 104 /* ThisKeyword */ && ts.isExpression(location)) {
- return "parameter" /* parameterElement */;
- }
- var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol);
- if (flags & 3 /* Variable */) {
- if (ts.isFirstDeclarationOfSymbolParameter(symbol)) {
- return "parameter" /* parameterElement */;
- }
- else if (symbol.valueDeclaration && ts.isVarConst(symbol.valueDeclaration)) {
- return "const" /* constElement */;
- }
- else if (ts.forEach(symbol.declarations, ts.isLet)) {
- return "let" /* letElement */;
- }
- return isLocalVariableOrFunction(symbol) ? "local var" /* localVariableElement */ : "var" /* variableElement */;
- }
- if (flags & 16 /* Function */)
- return isLocalVariableOrFunction(symbol) ? "local function" /* localFunctionElement */ : "function" /* functionElement */;
- if (flags & 32768 /* GetAccessor */)
- return "getter" /* memberGetAccessorElement */;
- if (flags & 65536 /* SetAccessor */)
- return "setter" /* memberSetAccessorElement */;
- if (flags & 8192 /* Method */)
- return "method" /* memberFunctionElement */;
- if (flags & 16384 /* Constructor */)
- return "constructor" /* constructorImplementationElement */;
- if (flags & 4 /* Property */) {
- if (flags & 33554432 /* Transient */ && symbol.checkFlags & 6 /* Synthetic */) {
- // If union property is result of union of non method (property/accessors/variables), it is labeled as property
- var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) {
- var rootSymbolFlags = rootSymbol.getFlags();
- if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) {
- return "property" /* memberVariableElement */;
- }
- // May be a Function if this was from `typeof N` with `namespace N { function f();. }`.
- ts.Debug.assert(!!(rootSymbolFlags & (8192 /* Method */ | 16 /* Function */)));
- });
- if (!unionPropertyKind) {
- // If this was union of all methods,
- // make sure it has call signatures before we can label it as method
- var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location);
- if (typeOfUnionProperty.getCallSignatures().length) {
- return "method" /* memberFunctionElement */;
- }
- return "property" /* memberVariableElement */;
- }
- return unionPropertyKind;
- }
- // If we requested completions after `x.` at the top-level, we may be at a source file location.
- switch (location.parent && location.parent.kind) {
- // If we've typed a character of the attribute name, will be 'JsxAttribute', else will be 'JsxOpeningElement'.
- case 268 /* JsxOpeningElement */:
- case 266 /* JsxElement */:
- case 267 /* JsxSelfClosingElement */:
- return location.kind === 75 /* Identifier */ ? "property" /* memberVariableElement */ : "JSX attribute" /* jsxAttribute */;
- case 273 /* JsxAttribute */:
- return "JSX attribute" /* jsxAttribute */;
- default:
- return "property" /* memberVariableElement */;
- }
- }
- return "" /* unknown */;
- }
- function getSymbolModifiers(symbol) {
- var nodeModifiers = symbol && symbol.declarations && symbol.declarations.length > 0
- ? ts.getNodeModifiers(symbol.declarations[0])
- : "" /* none */;
- var symbolModifiers = symbol && symbol.flags & 16777216 /* Optional */ ?
- "optional" /* optionalModifier */
- : "" /* none */;
- return nodeModifiers && symbolModifiers ? nodeModifiers + "," + symbolModifiers : nodeModifiers || symbolModifiers;
- }
- SymbolDisplay.getSymbolModifiers = getSymbolModifiers;
- // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
- function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, enclosingDeclaration, location, semanticMeaning, alias) {
- if (semanticMeaning === void 0) { semanticMeaning = ts.getMeaningFromLocation(location); }
- var displayParts = [];
- var documentation = [];
- var tags = [];
- var symbolFlags = ts.getCombinedLocalAndExportSymbolFlags(symbol);
- var symbolKind = semanticMeaning & 1 /* Value */ ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) : "" /* unknown */;
- var hasAddedSymbolInfo = false;
- var isThisExpression = location.kind === 104 /* ThisKeyword */ && ts.isInExpressionContext(location);
- var type;
- var printer;
- var documentationFromAlias;
- var tagsFromAlias;
- var hasMultipleSignatures = false;
- if (location.kind === 104 /* ThisKeyword */ && !isThisExpression) {
- return { displayParts: [ts.keywordPart(104 /* ThisKeyword */)], documentation: [], symbolKind: "primitive type" /* primitiveType */, tags: undefined };
- }
- // Class at constructor site need to be shown as constructor apart from property,method, vars
- if (symbolKind !== "" /* unknown */ || symbolFlags & 32 /* Class */ || symbolFlags & 2097152 /* Alias */) {
- // If it is accessor they are allowed only if location is at name of the accessor
- if (symbolKind === "getter" /* memberGetAccessorElement */ || symbolKind === "setter" /* memberSetAccessorElement */) {
- symbolKind = "property" /* memberVariableElement */;
- }
- var signature = void 0;
- type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol.exportSymbol || symbol, location);
- if (location.parent && location.parent.kind === 194 /* PropertyAccessExpression */) {
- var right = location.parent.name;
- // Either the location is on the right of a property access, or on the left and the right is missing
- if (right === location || (right && right.getFullWidth() === 0)) {
- location = location.parent;
- }
- }
- // try get the call/construct signature from the type if it matches
- var callExpressionLike = void 0;
- if (ts.isCallOrNewExpression(location)) {
- callExpressionLike = location;
- }
- else if (ts.isCallExpressionTarget(location) || ts.isNewExpressionTarget(location)) {
- callExpressionLike = location.parent;
- }
- else if (location.parent && ts.isJsxOpeningLikeElement(location.parent) && ts.isFunctionLike(symbol.valueDeclaration)) {
- callExpressionLike = location.parent;
- }
- if (callExpressionLike) {
- signature = typeChecker.getResolvedSignature(callExpressionLike); // TODO: GH#18217
- var useConstructSignatures = callExpressionLike.kind === 197 /* NewExpression */ || (ts.isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === 102 /* SuperKeyword */);
- var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures();
- if (!ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) {
- // Get the first signature if there is one -- allSignatures may contain
- // either the original signature or its target, so check for either
- signature = allSignatures.length ? allSignatures[0] : undefined;
- }
- if (signature) {
- if (useConstructSignatures && (symbolFlags & 32 /* Class */)) {
- // Constructor
- symbolKind = "constructor" /* constructorImplementationElement */;
- addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
- }
- else if (symbolFlags & 2097152 /* Alias */) {
- symbolKind = "alias" /* alias */;
- pushSymbolKind(symbolKind);
- displayParts.push(ts.spacePart());
- if (useConstructSignatures) {
- displayParts.push(ts.keywordPart(99 /* NewKeyword */));
- displayParts.push(ts.spacePart());
- }
- addFullSymbolName(symbol);
- }
- else {
- addPrefixForAnyFunctionOrVar(symbol, symbolKind);
- }
- switch (symbolKind) {
- case "JSX attribute" /* jsxAttribute */:
- case "property" /* memberVariableElement */:
- case "var" /* variableElement */:
- case "const" /* constElement */:
- case "let" /* letElement */:
- case "parameter" /* parameterElement */:
- case "local var" /* localVariableElement */:
- // If it is call or construct signature of lambda's write type name
- displayParts.push(ts.punctuationPart(58 /* ColonToken */));
- displayParts.push(ts.spacePart());
- if (!(ts.getObjectFlags(type) & 16 /* Anonymous */) && type.symbol) {
- ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 4 /* AllowAnyNodeKind */ | 1 /* WriteTypeParametersOrArguments */));
- displayParts.push(ts.lineBreakPart());
- }
- if (useConstructSignatures) {
- displayParts.push(ts.keywordPart(99 /* NewKeyword */));
- displayParts.push(ts.spacePart());
- }
- addSignatureDisplayParts(signature, allSignatures, 262144 /* WriteArrowStyleSignature */);
- break;
- default:
- // Just signature
- addSignatureDisplayParts(signature, allSignatures);
- }
- hasAddedSymbolInfo = true;
- hasMultipleSignatures = allSignatures.length > 1;
- }
- }
- else if ((ts.isNameOfFunctionDeclaration(location) && !(symbolFlags & 98304 /* Accessor */)) || // name of function declaration
- (location.kind === 129 /* ConstructorKeyword */ && location.parent.kind === 162 /* Constructor */)) { // At constructor keyword of constructor declaration
- // get the signature from the declaration and write it
- var functionDeclaration_1 = location.parent;
- // Use function declaration to write the signatures only if the symbol corresponding to this declaration
- var locationIsSymbolDeclaration = symbol.declarations && ts.find(symbol.declarations, function (declaration) {
- return declaration === (location.kind === 129 /* ConstructorKeyword */ ? functionDeclaration_1.parent : functionDeclaration_1);
- });
- if (locationIsSymbolDeclaration) {
- var allSignatures = functionDeclaration_1.kind === 162 /* Constructor */ ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures();
- if (!typeChecker.isImplementationOfOverload(functionDeclaration_1)) {
- signature = typeChecker.getSignatureFromDeclaration(functionDeclaration_1); // TODO: GH#18217
- }
- else {
- signature = allSignatures[0];
- }
- if (functionDeclaration_1.kind === 162 /* Constructor */) {
- // show (constructor) Type(...) signature
- symbolKind = "constructor" /* constructorImplementationElement */;
- addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
- }
- else {
- // (function/method) symbol(..signature)
- addPrefixForAnyFunctionOrVar(functionDeclaration_1.kind === 165 /* CallSignature */ &&
- !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind);
- }
- addSignatureDisplayParts(signature, allSignatures);
- hasAddedSymbolInfo = true;
- hasMultipleSignatures = allSignatures.length > 1;
- }
- }
- }
- if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo && !isThisExpression) {
- addAliasPrefixIfNecessary();
- if (ts.getDeclarationOfKind(symbol, 214 /* ClassExpression */)) {
- // Special case for class expressions because we would like to indicate that
- // the class name is local to the class body (similar to function expression)
- // (local class) class
- pushSymbolKind("local class" /* localClassElement */);
- }
- else {
- // Class declaration has name which is not local.
- displayParts.push(ts.keywordPart(80 /* ClassKeyword */));
- }
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- writeTypeParametersOfSymbol(symbol, sourceFile);
- }
- if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) {
- prefixNextMeaning();
- displayParts.push(ts.keywordPart(114 /* InterfaceKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- writeTypeParametersOfSymbol(symbol, sourceFile);
- }
- if ((symbolFlags & 524288 /* TypeAlias */) && (semanticMeaning & 2 /* Type */)) {
- prefixNextMeaning();
- displayParts.push(ts.keywordPart(145 /* TypeKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- writeTypeParametersOfSymbol(symbol, sourceFile);
- displayParts.push(ts.spacePart());
- displayParts.push(ts.operatorPart(62 /* EqualsToken */));
- displayParts.push(ts.spacePart());
- ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 8388608 /* InTypeAlias */));
- }
- if (symbolFlags & 384 /* Enum */) {
- prefixNextMeaning();
- if (ts.some(symbol.declarations, function (d) { return ts.isEnumDeclaration(d) && ts.isEnumConst(d); })) {
- displayParts.push(ts.keywordPart(81 /* ConstKeyword */));
- displayParts.push(ts.spacePart());
- }
- displayParts.push(ts.keywordPart(88 /* EnumKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- }
- if (symbolFlags & 1536 /* Module */ && !isThisExpression) {
- prefixNextMeaning();
- var declaration = ts.getDeclarationOfKind(symbol, 249 /* ModuleDeclaration */);
- var isNamespace = declaration && declaration.name && declaration.name.kind === 75 /* Identifier */;
- displayParts.push(ts.keywordPart(isNamespace ? 136 /* NamespaceKeyword */ : 135 /* ModuleKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- }
- if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) {
- prefixNextMeaning();
- displayParts.push(ts.punctuationPart(20 /* OpenParenToken */));
- displayParts.push(ts.textPart("type parameter"));
- displayParts.push(ts.punctuationPart(21 /* CloseParenToken */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- if (symbol.parent) {
- // Class/Interface type parameter
- addInPrefix();
- addFullSymbolName(symbol.parent, enclosingDeclaration);
- writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration);
- }
- else {
- // Method/function type parameter
- var decl = ts.getDeclarationOfKind(symbol, 155 /* TypeParameter */);
- if (decl === undefined)
- return ts.Debug.fail();
- var declaration = decl.parent;
- if (declaration) {
- if (ts.isFunctionLikeKind(declaration.kind)) {
- addInPrefix();
- var signature = typeChecker.getSignatureFromDeclaration(declaration); // TODO: GH#18217
- if (declaration.kind === 166 /* ConstructSignature */) {
- displayParts.push(ts.keywordPart(99 /* NewKeyword */));
- displayParts.push(ts.spacePart());
- }
- else if (declaration.kind !== 165 /* CallSignature */ && declaration.name) {
- addFullSymbolName(declaration.symbol);
- }
- ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */));
- }
- else if (declaration.kind === 247 /* TypeAliasDeclaration */) {
- // Type alias type parameter
- // For example
- // type list = T[]; // Both T will go through same code path
- addInPrefix();
- displayParts.push(ts.keywordPart(145 /* TypeKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(declaration.symbol);
- writeTypeParametersOfSymbol(declaration.symbol, sourceFile);
- }
- }
- }
- }
- if (symbolFlags & 8 /* EnumMember */) {
- symbolKind = "enum member" /* enumMemberElement */;
- addPrefixForAnyFunctionOrVar(symbol, "enum member");
- var declaration = symbol.declarations[0];
- if (declaration.kind === 284 /* EnumMember */) {
- var constantValue = typeChecker.getConstantValue(declaration);
- if (constantValue !== undefined) {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.operatorPart(62 /* EqualsToken */));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.displayPart(ts.getTextOfConstantValue(constantValue), typeof constantValue === "number" ? ts.SymbolDisplayPartKind.numericLiteral : ts.SymbolDisplayPartKind.stringLiteral));
- }
- }
- }
- if (symbolFlags & 2097152 /* Alias */) {
- prefixNextMeaning();
- if (!hasAddedSymbolInfo) {
- var resolvedSymbol = typeChecker.getAliasedSymbol(symbol);
- if (resolvedSymbol !== symbol && resolvedSymbol.declarations && resolvedSymbol.declarations.length > 0) {
- var resolvedNode = resolvedSymbol.declarations[0];
- var declarationName = ts.getNameOfDeclaration(resolvedNode);
- if (declarationName) {
- var isExternalModuleDeclaration = ts.isModuleWithStringLiteralName(resolvedNode) &&
- ts.hasModifier(resolvedNode, 2 /* Ambient */);
- var shouldUseAliasName = symbol.name !== "default" && !isExternalModuleDeclaration;
- var resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, resolvedSymbol, ts.getSourceFileOfNode(resolvedNode), resolvedNode, declarationName, semanticMeaning, shouldUseAliasName ? symbol : resolvedSymbol);
- displayParts.push.apply(displayParts, resolvedInfo.displayParts);
- displayParts.push(ts.lineBreakPart());
- documentationFromAlias = resolvedInfo.documentation;
- tagsFromAlias = resolvedInfo.tags;
- }
- }
- }
- switch (symbol.declarations[0].kind) {
- case 252 /* NamespaceExportDeclaration */:
- displayParts.push(ts.keywordPart(89 /* ExportKeyword */));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.keywordPart(136 /* NamespaceKeyword */));
- break;
- case 259 /* ExportAssignment */:
- displayParts.push(ts.keywordPart(89 /* ExportKeyword */));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.keywordPart(symbol.declarations[0].isExportEquals ? 62 /* EqualsToken */ : 84 /* DefaultKeyword */));
- break;
- case 263 /* ExportSpecifier */:
- displayParts.push(ts.keywordPart(89 /* ExportKeyword */));
- break;
- default:
- displayParts.push(ts.keywordPart(96 /* ImportKeyword */));
- }
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- ts.forEach(symbol.declarations, function (declaration) {
- if (declaration.kind === 253 /* ImportEqualsDeclaration */) {
- var importEqualsDeclaration = declaration;
- if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.operatorPart(62 /* EqualsToken */));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.keywordPart(139 /* RequireKeyword */));
- displayParts.push(ts.punctuationPart(20 /* OpenParenToken */));
- displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral));
- displayParts.push(ts.punctuationPart(21 /* CloseParenToken */));
- }
- else {
- var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference);
- if (internalAliasSymbol) {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.operatorPart(62 /* EqualsToken */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(internalAliasSymbol, enclosingDeclaration);
- }
- }
- return true;
- }
- });
- }
- if (!hasAddedSymbolInfo) {
- if (symbolKind !== "" /* unknown */) {
- if (type) {
- if (isThisExpression) {
- prefixNextMeaning();
- displayParts.push(ts.keywordPart(104 /* ThisKeyword */));
- }
- else {
- addPrefixForAnyFunctionOrVar(symbol, symbolKind);
- }
- // For properties, variables and local vars: show the type
- if (symbolKind === "property" /* memberVariableElement */ ||
- symbolKind === "JSX attribute" /* jsxAttribute */ ||
- symbolFlags & 3 /* Variable */ ||
- symbolKind === "local var" /* localVariableElement */ ||
- isThisExpression) {
- displayParts.push(ts.punctuationPart(58 /* ColonToken */));
- displayParts.push(ts.spacePart());
- // If the type is type parameter, format it specially
- if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) {
- var typeParameterParts = ts.mapToDisplayParts(function (writer) {
- var param = typeChecker.typeParameterToDeclaration(type, enclosingDeclaration, symbolDisplayNodeBuilderFlags);
- getPrinter().writeNode(4 /* Unspecified */, param, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer);
- });
- ts.addRange(displayParts, typeParameterParts);
- }
- else {
- ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration));
- }
- }
- else if (symbolFlags & 16 /* Function */ ||
- symbolFlags & 8192 /* Method */ ||
- symbolFlags & 16384 /* Constructor */ ||
- symbolFlags & 131072 /* Signature */ ||
- symbolFlags & 98304 /* Accessor */ ||
- symbolKind === "method" /* memberFunctionElement */) {
- var allSignatures = type.getNonNullableType().getCallSignatures();
- if (allSignatures.length) {
- addSignatureDisplayParts(allSignatures[0], allSignatures);
- hasMultipleSignatures = allSignatures.length > 1;
- }
- }
- }
- }
- else {
- symbolKind = getSymbolKind(typeChecker, symbol, location);
- }
- }
- if (documentation.length === 0 && !hasMultipleSignatures) {
- documentation = symbol.getDocumentationComment(typeChecker);
- }
- if (documentation.length === 0 && symbolFlags & 4 /* Property */) {
- // For some special property access expressions like `exports.foo = foo` or `module.exports.foo = foo`
- // there documentation comments might be attached to the right hand side symbol of their declarations.
- // The pattern of such special property access is that the parent symbol is the symbol of the file.
- if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 290 /* SourceFile */; })) {
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (!declaration.parent || declaration.parent.kind !== 209 /* BinaryExpression */) {
- continue;
- }
- var rhsSymbol = typeChecker.getSymbolAtLocation(declaration.parent.right);
- if (!rhsSymbol) {
- continue;
- }
- documentation = rhsSymbol.getDocumentationComment(typeChecker);
- tags = rhsSymbol.getJsDocTags();
- if (documentation.length > 0) {
- break;
- }
- }
- }
- }
- if (tags.length === 0 && !hasMultipleSignatures) {
- tags = symbol.getJsDocTags();
- }
- if (documentation.length === 0 && documentationFromAlias) {
- documentation = documentationFromAlias;
- }
- if (tags.length === 0 && tagsFromAlias) {
- tags = tagsFromAlias;
- }
- return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind, tags: tags.length === 0 ? undefined : tags };
- function getPrinter() {
- if (!printer) {
- printer = ts.createPrinter({ removeComments: true });
- }
- return printer;
- }
- function prefixNextMeaning() {
- if (displayParts.length) {
- displayParts.push(ts.lineBreakPart());
- }
- addAliasPrefixIfNecessary();
- }
- function addAliasPrefixIfNecessary() {
- if (alias) {
- pushSymbolKind("alias" /* alias */);
- displayParts.push(ts.spacePart());
- }
- }
- function addInPrefix() {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.keywordPart(97 /* InKeyword */));
- displayParts.push(ts.spacePart());
- }
- function addFullSymbolName(symbolToDisplay, enclosingDeclaration) {
- if (alias && symbolToDisplay === symbol) {
- symbolToDisplay = alias;
- }
- var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */ | 4 /* AllowAnyNodeKind */);
- ts.addRange(displayParts, fullSymbolDisplayParts);
- if (symbol.flags & 16777216 /* Optional */) {
- displayParts.push(ts.punctuationPart(57 /* QuestionToken */));
- }
- }
- function addPrefixForAnyFunctionOrVar(symbol, symbolKind) {
- prefixNextMeaning();
- if (symbolKind) {
- pushSymbolKind(symbolKind);
- if (symbol && !ts.some(symbol.declarations, function (d) { return ts.isArrowFunction(d) || (ts.isFunctionExpression(d) || ts.isClassExpression(d)) && !d.name; })) {
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- }
- }
- }
- function pushSymbolKind(symbolKind) {
- switch (symbolKind) {
- case "var" /* variableElement */:
- case "function" /* functionElement */:
- case "let" /* letElement */:
- case "const" /* constElement */:
- case "constructor" /* constructorImplementationElement */:
- displayParts.push(ts.textOrKeywordPart(symbolKind));
- return;
- default:
- displayParts.push(ts.punctuationPart(20 /* OpenParenToken */));
- displayParts.push(ts.textOrKeywordPart(symbolKind));
- displayParts.push(ts.punctuationPart(21 /* CloseParenToken */));
- return;
- }
- }
- function addSignatureDisplayParts(signature, allSignatures, flags) {
- if (flags === void 0) { flags = 0 /* None */; }
- ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */));
- if (allSignatures.length > 1) {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.punctuationPart(20 /* OpenParenToken */));
- displayParts.push(ts.operatorPart(39 /* PlusToken */));
- displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads"));
- displayParts.push(ts.punctuationPart(21 /* CloseParenToken */));
- }
- documentation = signature.getDocumentationComment(typeChecker);
- tags = signature.getJsDocTags();
- if (allSignatures.length > 1 && documentation.length === 0 && tags.length === 0) {
- documentation = allSignatures[0].getDocumentationComment(typeChecker);
- tags = allSignatures[0].getJsDocTags();
- }
- }
- function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) {
- var typeParameterParts = ts.mapToDisplayParts(function (writer) {
- var params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration, symbolDisplayNodeBuilderFlags);
- getPrinter().writeList(53776 /* TypeParameters */, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer);
- });
- ts.addRange(displayParts, typeParameterParts);
- }
- }
- SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind;
- function isLocalVariableOrFunction(symbol) {
- if (symbol.parent) {
- return false; // This is exported symbol
- }
- return ts.forEach(symbol.declarations, function (declaration) {
- // Function expressions are local
- if (declaration.kind === 201 /* FunctionExpression */) {
- return true;
- }
- if (declaration.kind !== 242 /* VariableDeclaration */ && declaration.kind !== 244 /* FunctionDeclaration */) {
- return false;
- }
- // If the parent is not sourceFile or module block it is local variable
- for (var parent = declaration.parent; !ts.isFunctionBlock(parent); parent = parent.parent) {
- // Reached source file or module block
- if (parent.kind === 290 /* SourceFile */ || parent.kind === 250 /* ModuleBlock */) {
- return false;
- }
- }
- // parent is in function block
- return true;
- });
- }
- })(SymbolDisplay = ts.SymbolDisplay || (ts.SymbolDisplay = {}));
-})(ts || (ts = {}));
-var ts;
-(function (ts) {
- /*
- * This function will compile source text from 'input' argument using specified compiler options.
- * If not options are provided - it will use a set of default compiler options.
- * Extra compiler options that will unconditionally be used by this function are:
- * - isolatedModules = true
- * - allowNonTsExtensions = true
- * - noLib = true
- * - noResolve = true
- */
- function transpileModule(input, transpileOptions) {
- var diagnostics = [];
- var options = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : {};
- // mix in default options
- var defaultOptions = ts.getDefaultCompilerOptions();
- for (var key in defaultOptions) {
- if (ts.hasProperty(defaultOptions, key) && options[key] === undefined) {
- options[key] = defaultOptions[key];
- }
- }
- for (var _i = 0, transpileOptionValueCompilerOptions_1 = ts.transpileOptionValueCompilerOptions; _i < transpileOptionValueCompilerOptions_1.length; _i++) {
- var option = transpileOptionValueCompilerOptions_1[_i];
- options[option.name] = option.transpileOptionValue;
- }
- // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths.
- options.suppressOutputPathCheck = true;
- // Filename can be non-ts file.
- options.allowNonTsExtensions = true;
- // if jsx is specified then treat file as .tsx
- var inputFileName = transpileOptions.fileName || (transpileOptions.compilerOptions && transpileOptions.compilerOptions.jsx ? "module.tsx" : "module.ts");
- var sourceFile = ts.createSourceFile(inputFileName, input, options.target); // TODO: GH#18217
- if (transpileOptions.moduleName) {
- sourceFile.moduleName = transpileOptions.moduleName;
- }
- if (transpileOptions.renamedDependencies) {
- sourceFile.renamedDependencies = ts.createMapFromTemplate(transpileOptions.renamedDependencies);
- }
- var newLine = ts.getNewLineCharacter(options);
- // Output
- var outputText;
- var sourceMapText;
- // Create a compilerHost object to allow the compiler to read and write files
- var compilerHost = {
- getSourceFile: function (fileName) { return fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined; },
- writeFile: function (name, text) {
- if (ts.fileExtensionIs(name, ".map")) {
- ts.Debug.assertEqual(sourceMapText, undefined, "Unexpected multiple source map outputs, file:", name);
- sourceMapText = text;
- }
- else {
- ts.Debug.assertEqual(outputText, undefined, "Unexpected multiple outputs, file:", name);
- outputText = text;
- }
- },
- getDefaultLibFileName: function () { return "lib.d.ts"; },
- useCaseSensitiveFileNames: function () { return false; },
- getCanonicalFileName: function (fileName) { return fileName; },
- getCurrentDirectory: function () { return ""; },
- getNewLine: function () { return newLine; },
- fileExists: function (fileName) { return fileName === inputFileName; },
- readFile: function () { return ""; },
- directoryExists: function () { return true; },
- getDirectories: function () { return []; }
- };
- var program = ts.createProgram([inputFileName], options, compilerHost);
- if (transpileOptions.reportDiagnostics) {
- ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile));
- ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics());
- }
- // Emit
- program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers);
- if (outputText === undefined)
- return ts.Debug.fail("Output generation failed");
- return { outputText: outputText, diagnostics: diagnostics, sourceMapText: sourceMapText };
- }
- ts.transpileModule = transpileModule;
- /*
- * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result.
- */
- function transpile(input, compilerOptions, fileName, diagnostics, moduleName) {
- var output = transpileModule(input, { compilerOptions: compilerOptions, fileName: fileName, reportDiagnostics: !!diagnostics, moduleName: moduleName });
- // addRange correctly handles cases when wither 'from' or 'to' argument is missing
- ts.addRange(diagnostics, output.diagnostics);
- return output.outputText;
- }
- ts.transpile = transpile;
- var commandLineOptionsStringToEnum;
- /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */
- /*@internal*/
- function fixupCompilerOptions(options, diagnostics) {
- // Lazily create this value to fix module loading errors.
- commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || ts.filter(ts.optionDeclarations, function (o) {
- return typeof o.type === "object" && !ts.forEachEntry(o.type, function (v) { return typeof v !== "number"; });
- });
- options = ts.cloneCompilerOptions(options);
- var _loop_8 = function (opt) {
- if (!ts.hasProperty(options, opt.name)) {
- return "continue";
- }
- var value = options[opt.name];
- // Value should be a key of opt.type
- if (ts.isString(value)) {
- // If value is not a string, this will fail
- options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics);
- }
- else {
- if (!ts.forEachEntry(opt.type, function (v) { return v === value; })) {
- // Supplied value isn't a valid enum value.
- diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt));
- }
- }
- };
- for (var _i = 0, commandLineOptionsStringToEnum_1 = commandLineOptionsStringToEnum; _i < commandLineOptionsStringToEnum_1.length; _i++) {
- var opt = commandLineOptionsStringToEnum_1[_i];
- _loop_8(opt);
- }
- return options;
- }
- ts.fixupCompilerOptions = fixupCompilerOptions;
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- var FormattingRequestKind;
- (function (FormattingRequestKind) {
- FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument";
- FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection";
- FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter";
- FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon";
- FormattingRequestKind[FormattingRequestKind["FormatOnOpeningCurlyBrace"] = 4] = "FormatOnOpeningCurlyBrace";
- FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 5] = "FormatOnClosingCurlyBrace";
- })(FormattingRequestKind = formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {}));
- var FormattingContext = /** @class */ (function () {
- function FormattingContext(sourceFile, formattingRequestKind, options) {
- this.sourceFile = sourceFile;
- this.formattingRequestKind = formattingRequestKind;
- this.options = options;
- }
- FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) {
- this.currentTokenSpan = ts.Debug.checkDefined(currentRange);
- this.currentTokenParent = ts.Debug.checkDefined(currentTokenParent);
- this.nextTokenSpan = ts.Debug.checkDefined(nextRange);
- this.nextTokenParent = ts.Debug.checkDefined(nextTokenParent);
- this.contextNode = ts.Debug.checkDefined(commonParent);
- // drop cached results
- this.contextNodeAllOnSameLine = undefined;
- this.nextNodeAllOnSameLine = undefined;
- this.tokensAreOnSameLine = undefined;
- this.contextNodeBlockIsOnOneLine = undefined;
- this.nextNodeBlockIsOnOneLine = undefined;
- };
- FormattingContext.prototype.ContextNodeAllOnSameLine = function () {
- if (this.contextNodeAllOnSameLine === undefined) {
- this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode);
- }
- return this.contextNodeAllOnSameLine;
- };
- FormattingContext.prototype.NextNodeAllOnSameLine = function () {
- if (this.nextNodeAllOnSameLine === undefined) {
- this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent);
- }
- return this.nextNodeAllOnSameLine;
- };
- FormattingContext.prototype.TokensAreOnSameLine = function () {
- if (this.tokensAreOnSameLine === undefined) {
- var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
- var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
- this.tokensAreOnSameLine = (startLine === endLine);
- }
- return this.tokensAreOnSameLine;
- };
- FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () {
- if (this.contextNodeBlockIsOnOneLine === undefined) {
- this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode);
- }
- return this.contextNodeBlockIsOnOneLine;
- };
- FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () {
- if (this.nextNodeBlockIsOnOneLine === undefined) {
- this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent);
- }
- return this.nextNodeBlockIsOnOneLine;
- };
- FormattingContext.prototype.NodeIsOnOneLine = function (node) {
- var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
- var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
- return startLine === endLine;
- };
- FormattingContext.prototype.BlockIsOnOneLine = function (node) {
- var openBrace = ts.findChildOfKind(node, 18 /* OpenBraceToken */, this.sourceFile);
- var closeBrace = ts.findChildOfKind(node, 19 /* CloseBraceToken */, this.sourceFile);
- if (openBrace && closeBrace) {
- var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
- var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
- return startLine === endLine;
- }
- return false;
- };
- return FormattingContext;
- }());
- formatting.FormattingContext = FormattingContext;
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- var standardScanner = ts.createScanner(99 /* Latest */, /*skipTrivia*/ false, 0 /* Standard */);
- var jsxScanner = ts.createScanner(99 /* Latest */, /*skipTrivia*/ false, 1 /* JSX */);
- var ScanAction;
- (function (ScanAction) {
- ScanAction[ScanAction["Scan"] = 0] = "Scan";
- ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken";
- ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken";
- ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken";
- ScanAction[ScanAction["RescanJsxIdentifier"] = 4] = "RescanJsxIdentifier";
- ScanAction[ScanAction["RescanJsxText"] = 5] = "RescanJsxText";
- ScanAction[ScanAction["RescanJsxAttributeValue"] = 6] = "RescanJsxAttributeValue";
- })(ScanAction || (ScanAction = {}));
- function getFormattingScanner(text, languageVariant, startPos, endPos, cb) {
- var scanner = languageVariant === 1 /* JSX */ ? jsxScanner : standardScanner;
- scanner.setText(text);
- scanner.setTextPos(startPos);
- var wasNewLine = true;
- var leadingTrivia;
- var trailingTrivia;
- var savedPos;
- var lastScanAction;
- var lastTokenInfo;
- var res = cb({
- advance: advance,
- readTokenInfo: readTokenInfo,
- readEOFTokenRange: readEOFTokenRange,
- isOnToken: isOnToken,
- isOnEOF: isOnEOF,
- getCurrentLeadingTrivia: function () { return leadingTrivia; },
- lastTrailingTriviaWasNewLine: function () { return wasNewLine; },
- skipToEndOf: skipToEndOf,
- });
- lastTokenInfo = undefined;
- scanner.setText(undefined);
- return res;
- function advance() {
- lastTokenInfo = undefined;
- var isStarted = scanner.getStartPos() !== startPos;
- if (isStarted) {
- wasNewLine = !!trailingTrivia && ts.last(trailingTrivia).kind === 4 /* NewLineTrivia */;
- }
- else {
- scanner.scan();
- }
- leadingTrivia = undefined;
- trailingTrivia = undefined;
- var pos = scanner.getStartPos();
- // Read leading trivia and token
- while (pos < endPos) {
- var t = scanner.getToken();
- if (!ts.isTrivia(t)) {
- break;
- }
- // consume leading trivia
- scanner.scan();
- var item = {
- pos: pos,
- end: scanner.getStartPos(),
- kind: t
- };
- pos = scanner.getStartPos();
- leadingTrivia = ts.append(leadingTrivia, item);
- }
- savedPos = scanner.getStartPos();
- }
- function shouldRescanGreaterThanToken(node) {
- switch (node.kind) {
- case 33 /* GreaterThanEqualsToken */:
- case 70 /* GreaterThanGreaterThanEqualsToken */:
- case 71 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
- case 49 /* GreaterThanGreaterThanGreaterThanToken */:
- case 48 /* GreaterThanGreaterThanToken */:
- return true;
- }
- return false;
- }
- function shouldRescanJsxIdentifier(node) {
- if (node.parent) {
- switch (node.parent.kind) {
- case 273 /* JsxAttribute */:
- case 268 /* JsxOpeningElement */:
- case 269 /* JsxClosingElement */:
- case 267 /* JsxSelfClosingElement */:
- // May parse an identifier like `module-layout`; that will be scanned as a keyword at first, but we should parse the whole thing to get an identifier.
- return ts.isKeyword(node.kind) || node.kind === 75 /* Identifier */;
- }
- }
- return false;
- }
- function shouldRescanJsxText(node) {
- var isJSXText = ts.isJsxText(node);
- if (isJSXText) {
- var containingElement = ts.findAncestor(node.parent, function (p) { return ts.isJsxElement(p); });
- if (!containingElement)
- return false; // should never happen
- return !ts.isParenthesizedExpression(containingElement.parent);
- }
- return false;
- }
- function shouldRescanSlashToken(container) {
- return container.kind === 13 /* RegularExpressionLiteral */;
- }
- function shouldRescanTemplateToken(container) {
- return container.kind === 16 /* TemplateMiddle */ ||
- container.kind === 17 /* TemplateTail */;
- }
- function shouldRescanJsxAttributeValue(node) {
- return node.parent && ts.isJsxAttribute(node.parent) && node.parent.initializer === node;
- }
- function startsWithSlashToken(t) {
- return t === 43 /* SlashToken */ || t === 67 /* SlashEqualsToken */;
- }
- function readTokenInfo(n) {
- ts.Debug.assert(isOnToken());
- // normally scanner returns the smallest available token
- // check the kind of context node to determine if scanner should have more greedy behavior and consume more text.
- var expectedScanAction = shouldRescanGreaterThanToken(n) ? 1 /* RescanGreaterThanToken */ :
- shouldRescanSlashToken(n) ? 2 /* RescanSlashToken */ :
- shouldRescanTemplateToken(n) ? 3 /* RescanTemplateToken */ :
- shouldRescanJsxIdentifier(n) ? 4 /* RescanJsxIdentifier */ :
- shouldRescanJsxText(n) ? 5 /* RescanJsxText */ :
- shouldRescanJsxAttributeValue(n) ? 6 /* RescanJsxAttributeValue */ :
- 0 /* Scan */;
- if (lastTokenInfo && expectedScanAction === lastScanAction) {
- // readTokenInfo was called before with the same expected scan action.
- // No need to re-scan text, return existing 'lastTokenInfo'
- // it is ok to call fixTokenKind here since it does not affect
- // what portion of text is consumed. In contrast rescanning can change it,
- // i.e. for '>=' when originally scanner eats just one character
- // and rescanning forces it to consume more.
- return fixTokenKind(lastTokenInfo, n);
- }
- if (scanner.getStartPos() !== savedPos) {
- ts.Debug.assert(lastTokenInfo !== undefined);
- // readTokenInfo was called before but scan action differs - rescan text
- scanner.setTextPos(savedPos);
- scanner.scan();
- }
- var currentToken = getNextToken(n, expectedScanAction);
- var token = formatting.createTextRangeWithKind(scanner.getStartPos(), scanner.getTextPos(), currentToken);
- // consume trailing trivia
- if (trailingTrivia) {
- trailingTrivia = undefined;
- }
- while (scanner.getStartPos() < endPos) {
- currentToken = scanner.scan();
- if (!ts.isTrivia(currentToken)) {
- break;
- }
- var trivia = formatting.createTextRangeWithKind(scanner.getStartPos(), scanner.getTextPos(), currentToken);
- if (!trailingTrivia) {
- trailingTrivia = [];
- }
- trailingTrivia.push(trivia);
- if (currentToken === 4 /* NewLineTrivia */) {
- // move past new line
- scanner.scan();
- break;
- }
- }
- lastTokenInfo = { leadingTrivia: leadingTrivia, trailingTrivia: trailingTrivia, token: token };
- return fixTokenKind(lastTokenInfo, n);
- }
- function getNextToken(n, expectedScanAction) {
- var token = scanner.getToken();
- lastScanAction = 0 /* Scan */;
- switch (expectedScanAction) {
- case 1 /* RescanGreaterThanToken */:
- if (token === 31 /* GreaterThanToken */) {
- lastScanAction = 1 /* RescanGreaterThanToken */;
- var newToken = scanner.reScanGreaterToken();
- ts.Debug.assert(n.kind === newToken);
- return newToken;
- }
- break;
- case 2 /* RescanSlashToken */:
- if (startsWithSlashToken(token)) {
- lastScanAction = 2 /* RescanSlashToken */;
- var newToken = scanner.reScanSlashToken();
- ts.Debug.assert(n.kind === newToken);
- return newToken;
- }
- break;
- case 3 /* RescanTemplateToken */:
- if (token === 19 /* CloseBraceToken */) {
- lastScanAction = 3 /* RescanTemplateToken */;
- return scanner.reScanTemplateToken(/* isTaggedTemplate */ false);
- }
- break;
- case 4 /* RescanJsxIdentifier */:
- lastScanAction = 4 /* RescanJsxIdentifier */;
- return scanner.scanJsxIdentifier();
- case 5 /* RescanJsxText */:
- lastScanAction = 5 /* RescanJsxText */;
- return scanner.reScanJsxToken();
- case 6 /* RescanJsxAttributeValue */:
- lastScanAction = 6 /* RescanJsxAttributeValue */;
- return scanner.reScanJsxAttributeValue();
- case 0 /* Scan */:
- break;
- default:
- ts.Debug.assertNever(expectedScanAction);
- }
- return token;
- }
- function readEOFTokenRange() {
- ts.Debug.assert(isOnEOF());
- return formatting.createTextRangeWithKind(scanner.getStartPos(), scanner.getTextPos(), 1 /* EndOfFileToken */);
- }
- function isOnToken() {
- var current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
- var startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos();
- return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current);
- }
- function isOnEOF() {
- var current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
- return current === 1 /* EndOfFileToken */;
- }
- // when containing node in the tree is token
- // but its kind differs from the kind that was returned by the scanner,
- // then kind needs to be fixed. This might happen in cases
- // when parser interprets token differently, i.e keyword treated as identifier
- function fixTokenKind(tokenInfo, container) {
- if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) {
- tokenInfo.token.kind = container.kind;
- }
- return tokenInfo;
- }
- function skipToEndOf(node) {
- scanner.setTextPos(node.end);
- savedPos = scanner.getStartPos();
- lastScanAction = undefined;
- lastTokenInfo = undefined;
- wasNewLine = false;
- leadingTrivia = undefined;
- trailingTrivia = undefined;
- }
- }
- formatting.getFormattingScanner = getFormattingScanner;
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- formatting.anyContext = ts.emptyArray;
- var RuleAction;
- (function (RuleAction) {
- RuleAction[RuleAction["StopProcessingSpaceActions"] = 1] = "StopProcessingSpaceActions";
- RuleAction[RuleAction["StopProcessingTokenActions"] = 2] = "StopProcessingTokenActions";
- RuleAction[RuleAction["InsertSpace"] = 4] = "InsertSpace";
- RuleAction[RuleAction["InsertNewLine"] = 8] = "InsertNewLine";
- RuleAction[RuleAction["DeleteSpace"] = 16] = "DeleteSpace";
- RuleAction[RuleAction["DeleteToken"] = 32] = "DeleteToken";
- RuleAction[RuleAction["InsertTrailingSemicolon"] = 64] = "InsertTrailingSemicolon";
- RuleAction[RuleAction["StopAction"] = 3] = "StopAction";
- RuleAction[RuleAction["ModifySpaceAction"] = 28] = "ModifySpaceAction";
- RuleAction[RuleAction["ModifyTokenAction"] = 96] = "ModifyTokenAction";
- })(RuleAction = formatting.RuleAction || (formatting.RuleAction = {}));
- var RuleFlags;
- (function (RuleFlags) {
- RuleFlags[RuleFlags["None"] = 0] = "None";
- RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines";
- })(RuleFlags = formatting.RuleFlags || (formatting.RuleFlags = {}));
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- function getAllRules() {
- var allTokens = [];
- for (var token = 0 /* FirstToken */; token <= 152 /* LastToken */; token++) {
- if (token !== 1 /* EndOfFileToken */) {
- allTokens.push(token);
- }
- }
- function anyTokenExcept() {
- var tokens = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- tokens[_i] = arguments[_i];
- }
- return { tokens: allTokens.filter(function (t) { return !tokens.some(function (t2) { return t2 === t; }); }), isSpecific: false };
- }
- var anyToken = { tokens: allTokens, isSpecific: false };
- var anyTokenIncludingMultilineComments = tokenRangeFrom(__spreadArrays(allTokens, [3 /* MultiLineCommentTrivia */]));
- var anyTokenIncludingEOF = tokenRangeFrom(__spreadArrays(allTokens, [1 /* EndOfFileToken */]));
- var keywords = tokenRangeFromRange(77 /* FirstKeyword */, 152 /* LastKeyword */);
- var binaryOperators = tokenRangeFromRange(29 /* FirstBinaryOperator */, 74 /* LastBinaryOperator */);
- var binaryKeywordOperators = [97 /* InKeyword */, 98 /* InstanceOfKeyword */, 152 /* OfKeyword */, 123 /* AsKeyword */, 133 /* IsKeyword */];
- var unaryPrefixOperators = [45 /* PlusPlusToken */, 46 /* MinusMinusToken */, 54 /* TildeToken */, 53 /* ExclamationToken */];
- var unaryPrefixExpressions = [
- 8 /* NumericLiteral */, 9 /* BigIntLiteral */, 75 /* Identifier */, 20 /* OpenParenToken */,
- 22 /* OpenBracketToken */, 18 /* OpenBraceToken */, 104 /* ThisKeyword */, 99 /* NewKeyword */
- ];
- var unaryPreincrementExpressions = [75 /* Identifier */, 20 /* OpenParenToken */, 104 /* ThisKeyword */, 99 /* NewKeyword */];
- var unaryPostincrementExpressions = [75 /* Identifier */, 21 /* CloseParenToken */, 23 /* CloseBracketToken */, 99 /* NewKeyword */];
- var unaryPredecrementExpressions = [75 /* Identifier */, 20 /* OpenParenToken */, 104 /* ThisKeyword */, 99 /* NewKeyword */];
- var unaryPostdecrementExpressions = [75 /* Identifier */, 21 /* CloseParenToken */, 23 /* CloseBracketToken */, 99 /* NewKeyword */];
- var comments = [2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */];
- var typeNames = __spreadArrays([75 /* Identifier */], ts.typeKeywords);
- // Place a space before open brace in a function declaration
- // TypeScript: Function can have return types, which can be made of tons of different token kinds
- var functionOpenBraceLeftTokenRange = anyTokenIncludingMultilineComments;
- // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc)
- var typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([75 /* Identifier */, 3 /* MultiLineCommentTrivia */, 80 /* ClassKeyword */, 89 /* ExportKeyword */, 96 /* ImportKeyword */]);
- // Place a space before open brace in a control flow construct
- var controlOpenBraceLeftTokenRange = tokenRangeFrom([21 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 86 /* DoKeyword */, 107 /* TryKeyword */, 92 /* FinallyKeyword */, 87 /* ElseKeyword */]);
- // These rules are higher in priority than user-configurable
- var highPriorityCommonRules = [
- // Leave comments alone
- rule("IgnoreBeforeComment", anyToken, comments, formatting.anyContext, 1 /* StopProcessingSpaceActions */),
- rule("IgnoreAfterLineComment", 2 /* SingleLineCommentTrivia */, anyToken, formatting.anyContext, 1 /* StopProcessingSpaceActions */),
- rule("NotSpaceBeforeColon", anyToken, 58 /* ColonToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], 16 /* DeleteSpace */),
- rule("SpaceAfterColon", 58 /* ColonToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 4 /* InsertSpace */),
- rule("NoSpaceBeforeQuestionMark", anyToken, 57 /* QuestionToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 16 /* DeleteSpace */),
- // insert space after '?' only when it is used in conditional operator
- rule("SpaceAfterQuestionMarkInConditionalOperator", 57 /* QuestionToken */, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], 4 /* InsertSpace */),
- // in other cases there should be no space between '?' and next token
- rule("NoSpaceAfterQuestionMark", 57 /* QuestionToken */, anyToken, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeDot", anyToken, [24 /* DotToken */, 28 /* QuestionDotToken */], [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterDot", [24 /* DotToken */, 28 /* QuestionDotToken */], anyToken, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceBetweenImportParenInImportType", 96 /* ImportKeyword */, 20 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isImportTypeContext], 16 /* DeleteSpace */),
- // Special handling of unary operators.
- // Prefix operators generally shouldn't have a space between
- // them and their target unary expression.
- rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterUnaryPreincrementOperator", 45 /* PlusPlusToken */, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterUnaryPredecrementOperator", 46 /* MinusMinusToken */, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, 45 /* PlusPlusToken */, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, 46 /* MinusMinusToken */, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], 16 /* DeleteSpace */),
- // More unary operator special-casing.
- // DevDiv 181814: Be careful when removing leading whitespace
- // around unary operators. Examples:
- // 1 - -2 --X--> 1--2
- // a + ++b --X--> a+++b
- rule("SpaceAfterPostincrementWhenFollowedByAdd", 45 /* PlusPlusToken */, 39 /* PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("SpaceAfterAddWhenFollowedByUnaryPlus", 39 /* PlusToken */, 39 /* PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("SpaceAfterAddWhenFollowedByPreincrement", 39 /* PlusToken */, 45 /* PlusPlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("SpaceAfterPostdecrementWhenFollowedBySubtract", 46 /* MinusMinusToken */, 40 /* MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", 40 /* MinusToken */, 40 /* MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("SpaceAfterSubtractWhenFollowedByPredecrement", 40 /* MinusToken */, 46 /* MinusMinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterCloseBrace", 19 /* CloseBraceToken */, [27 /* CommaToken */, 26 /* SemicolonToken */], [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // For functions and control block place } on a new line [multi-line rule]
- rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, 19 /* CloseBraceToken */, [isMultilineBlockContext], 8 /* InsertNewLine */),
- // Space/new line after }.
- rule("SpaceAfterCloseBrace", 19 /* CloseBraceToken */, anyTokenExcept(21 /* CloseParenToken */), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], 4 /* InsertSpace */),
- // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied
- // Also should not apply to })
- rule("SpaceBetweenCloseBraceAndElse", 19 /* CloseBraceToken */, 87 /* ElseKeyword */, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceBetweenCloseBraceAndWhile", 19 /* CloseBraceToken */, 111 /* WhileKeyword */, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("NoSpaceBetweenEmptyBraceBrackets", 18 /* OpenBraceToken */, 19 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 16 /* DeleteSpace */),
- // Add a space after control dec context if the next character is an open bracket ex: 'if (false)[a, b] = [1, 2];' -> 'if (false) [a, b] = [1, 2];'
- rule("SpaceAfterConditionalClosingParen", 21 /* CloseParenToken */, 22 /* OpenBracketToken */, [isControlDeclContext], 4 /* InsertSpace */),
- rule("NoSpaceBetweenFunctionKeywordAndStar", 94 /* FunctionKeyword */, 41 /* AsteriskToken */, [isFunctionDeclarationOrFunctionExpressionContext], 16 /* DeleteSpace */),
- rule("SpaceAfterStarInGeneratorDeclaration", 41 /* AsteriskToken */, 75 /* Identifier */, [isFunctionDeclarationOrFunctionExpressionContext], 4 /* InsertSpace */),
- rule("SpaceAfterFunctionInFuncDecl", 94 /* FunctionKeyword */, anyToken, [isFunctionDeclContext], 4 /* InsertSpace */),
- // Insert new line after { and before } in multi-line contexts.
- rule("NewLineAfterOpenBraceInBlockContext", 18 /* OpenBraceToken */, anyToken, [isMultilineBlockContext], 8 /* InsertNewLine */),
- // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token.
- // Though, we do extra check on the context to make sure we are dealing with get/set node. Example:
- // get x() {}
- // set x(val) {}
- rule("SpaceAfterGetSetInMember", [131 /* GetKeyword */, 142 /* SetKeyword */], 75 /* Identifier */, [isFunctionDeclContext], 4 /* InsertSpace */),
- rule("NoSpaceBetweenYieldKeywordAndStar", 121 /* YieldKeyword */, 41 /* AsteriskToken */, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 16 /* DeleteSpace */),
- rule("SpaceBetweenYieldOrYieldStarAndOperand", [121 /* YieldKeyword */, 41 /* AsteriskToken */], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 4 /* InsertSpace */),
- rule("NoSpaceBetweenReturnAndSemicolon", 101 /* ReturnKeyword */, 26 /* SemicolonToken */, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("SpaceAfterCertainKeywords", [109 /* VarKeyword */, 105 /* ThrowKeyword */, 99 /* NewKeyword */, 85 /* DeleteKeyword */, 101 /* ReturnKeyword */, 108 /* TypeOfKeyword */, 127 /* AwaitKeyword */], anyToken, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceAfterLetConstInVariableDeclaration", [115 /* LetKeyword */, 81 /* ConstKeyword */], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], 4 /* InsertSpace */),
- rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, 20 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], 16 /* DeleteSpace */),
- // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options.
- rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("SpaceAfterVoidOperator", 110 /* VoidKeyword */, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], 4 /* InsertSpace */),
- // Async-await
- rule("SpaceBetweenAsyncAndOpenParen", 126 /* AsyncKeyword */, 20 /* OpenParenToken */, [isArrowFunctionContext, isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceBetweenAsyncAndFunctionKeyword", 126 /* AsyncKeyword */, [94 /* FunctionKeyword */, 75 /* Identifier */], [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- // Template string
- rule("NoSpaceBetweenTagAndTemplateString", [75 /* Identifier */, 21 /* CloseParenToken */], [14 /* NoSubstitutionTemplateLiteral */, 15 /* TemplateHead */], [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // JSX opening elements
- rule("SpaceBeforeJsxAttribute", anyToken, 75 /* Identifier */, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, 43 /* SlashToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", 43 /* SlashToken */, 31 /* GreaterThanToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, 62 /* EqualsToken */, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterEqualInJsxAttribute", 62 /* EqualsToken */, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // TypeScript-specific rules
- // Use of module as a function call. e.g.: import m2 = module("m2");
- rule("NoSpaceAfterModuleImport", [135 /* ModuleKeyword */, 139 /* RequireKeyword */], 20 /* OpenParenToken */, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // Add a space around certain TypeScript keywords
- rule("SpaceAfterCertainTypeScriptKeywords", [
- 122 /* AbstractKeyword */,
- 80 /* ClassKeyword */,
- 130 /* DeclareKeyword */,
- 84 /* DefaultKeyword */,
- 88 /* EnumKeyword */,
- 89 /* ExportKeyword */,
- 90 /* ExtendsKeyword */,
- 131 /* GetKeyword */,
- 113 /* ImplementsKeyword */,
- 96 /* ImportKeyword */,
- 114 /* InterfaceKeyword */,
- 135 /* ModuleKeyword */,
- 136 /* NamespaceKeyword */,
- 117 /* PrivateKeyword */,
- 119 /* PublicKeyword */,
- 118 /* ProtectedKeyword */,
- 138 /* ReadonlyKeyword */,
- 142 /* SetKeyword */,
- 120 /* StaticKeyword */,
- 145 /* TypeKeyword */,
- 149 /* FromKeyword */,
- 134 /* KeyOfKeyword */,
- 132 /* InferKeyword */,
- ], anyToken, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceBeforeCertainTypeScriptKeywords", anyToken, [90 /* ExtendsKeyword */, 113 /* ImplementsKeyword */, 149 /* FromKeyword */], [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" {
- rule("SpaceAfterModuleName", 10 /* StringLiteral */, 18 /* OpenBraceToken */, [isModuleDeclContext], 4 /* InsertSpace */),
- // Lambda expressions
- rule("SpaceBeforeArrow", anyToken, 38 /* EqualsGreaterThanToken */, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceAfterArrow", 38 /* EqualsGreaterThanToken */, anyToken, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- // Optional parameters and let args
- rule("NoSpaceAfterEllipsis", 25 /* DotDotDotToken */, 75 /* Identifier */, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterOptionalParameters", 57 /* QuestionToken */, [21 /* CloseParenToken */, 27 /* CommaToken */], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 16 /* DeleteSpace */),
- // Remove spaces in empty interface literals. e.g.: x: {}
- rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", 18 /* OpenBraceToken */, 19 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectTypeContext], 16 /* DeleteSpace */),
- // generics and type assertions
- rule("NoSpaceBeforeOpenAngularBracket", typeNames, 29 /* LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 16 /* DeleteSpace */),
- rule("NoSpaceBetweenCloseParenAndAngularBracket", 21 /* CloseParenToken */, 29 /* LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterOpenAngularBracket", 29 /* LessThanToken */, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeCloseAngularBracket", anyToken, 31 /* GreaterThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterCloseAngularBracket", 31 /* GreaterThanToken */, [20 /* OpenParenToken */, 22 /* OpenBracketToken */, 31 /* GreaterThanToken */, 27 /* CommaToken */], [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext /*To prevent an interference with the SpaceBeforeOpenParenInFuncDecl rule*/], 16 /* DeleteSpace */),
- // decorators
- rule("SpaceBeforeAt", [21 /* CloseParenToken */, 75 /* Identifier */], 59 /* AtToken */, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterAt", 59 /* AtToken */, anyToken, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // Insert space after @ in decorator
- rule("SpaceAfterDecorator", anyToken, [
- 122 /* AbstractKeyword */,
- 75 /* Identifier */,
- 89 /* ExportKeyword */,
- 84 /* DefaultKeyword */,
- 80 /* ClassKeyword */,
- 120 /* StaticKeyword */,
- 119 /* PublicKeyword */,
- 117 /* PrivateKeyword */,
- 118 /* ProtectedKeyword */,
- 131 /* GetKeyword */,
- 142 /* SetKeyword */,
- 22 /* OpenBracketToken */,
- 41 /* AsteriskToken */,
- ], [isEndOfDecoratorContextOnSameLine], 4 /* InsertSpace */),
- rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, 53 /* ExclamationToken */, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterNewKeywordOnConstructorSignature", 99 /* NewKeyword */, 20 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], 16 /* DeleteSpace */),
- rule("SpaceLessThanAndNonJSXTypeAnnotation", 29 /* LessThanToken */, 29 /* LessThanToken */, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- ];
- // These rules are applied after high priority
- var userConfigurableRules = [
- // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses
- rule("SpaceAfterConstructor", 129 /* ConstructorKeyword */, 20 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterConstructor", 129 /* ConstructorKeyword */, 20 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("SpaceAfterComma", 27 /* CommaToken */, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket, isNextTokenNotCloseParen], 4 /* InsertSpace */),
- rule("NoSpaceAfterComma", 27 /* CommaToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], 16 /* DeleteSpace */),
- // Insert space after function keyword for anonymous functions
- rule("SpaceAfterAnonymousFunctionKeyword", [94 /* FunctionKeyword */, 41 /* AsteriskToken */], 20 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterAnonymousFunctionKeyword", [94 /* FunctionKeyword */, 41 /* AsteriskToken */], 20 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 16 /* DeleteSpace */),
- // Insert space after keywords in control flow statements
- rule("SpaceAfterKeywordInControl", keywords, 20 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterKeywordInControl", keywords, 20 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 16 /* DeleteSpace */),
- // Insert space after opening and before closing nonempty parenthesis
- rule("SpaceAfterOpenParen", 20 /* OpenParenToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceBeforeCloseParen", anyToken, 21 /* CloseParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceBetweenOpenParens", 20 /* OpenParenToken */, 20 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("NoSpaceBetweenParens", 20 /* OpenParenToken */, 21 /* CloseParenToken */, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterOpenParen", 20 /* OpenParenToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeCloseParen", anyToken, 21 /* CloseParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // Insert space after opening and before closing nonempty brackets
- rule("SpaceAfterOpenBracket", 22 /* OpenBracketToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceBeforeCloseBracket", anyToken, 23 /* CloseBracketToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("NoSpaceBetweenBrackets", 22 /* OpenBracketToken */, 23 /* CloseBracketToken */, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterOpenBracket", 22 /* OpenBracketToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeCloseBracket", anyToken, 23 /* CloseBracketToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
- rule("SpaceAfterOpenBrace", 18 /* OpenBraceToken */, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 4 /* InsertSpace */),
- rule("SpaceBeforeCloseBrace", anyToken, 19 /* CloseBraceToken */, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 4 /* InsertSpace */),
- rule("NoSpaceBetweenEmptyBraceBrackets", 18 /* OpenBraceToken */, 19 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterOpenBrace", 18 /* OpenBraceToken */, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeCloseBrace", anyToken, 19 /* CloseBraceToken */, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // Insert a space after opening and before closing empty brace brackets
- rule("SpaceBetweenEmptyBraceBrackets", 18 /* OpenBraceToken */, 19 /* CloseBraceToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces")], 4 /* InsertSpace */),
- rule("NoSpaceBetweenEmptyBraceBrackets", 18 /* OpenBraceToken */, 19 /* CloseBraceToken */, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // Insert space after opening and before closing template string braces
- rule("SpaceAfterTemplateHeadAndMiddle", [15 /* TemplateHead */, 16 /* TemplateMiddle */], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [16 /* TemplateMiddle */, 17 /* TemplateTail */], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterTemplateHeadAndMiddle", [15 /* TemplateHead */, 16 /* TemplateMiddle */], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [16 /* TemplateMiddle */, 17 /* TemplateTail */], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // No space after { and before } in JSX expression
- rule("SpaceAfterOpenBraceInJsxExpression", 18 /* OpenBraceToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 4 /* InsertSpace */),
- rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, 19 /* CloseBraceToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterOpenBraceInJsxExpression", 18 /* OpenBraceToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 16 /* DeleteSpace */),
- rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, 19 /* CloseBraceToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 16 /* DeleteSpace */),
- // Insert space after semicolon in for statement
- rule("SpaceAfterSemicolonInFor", 26 /* SemicolonToken */, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterSemicolonInFor", 26 /* SemicolonToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 16 /* DeleteSpace */),
- // Insert space before and after binary operators
- rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* InsertSpace */),
- rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 16 /* DeleteSpace */),
- rule("SpaceBeforeOpenParenInFuncDecl", anyToken, 20 /* OpenParenToken */, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 4 /* InsertSpace */),
- rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, 20 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 16 /* DeleteSpace */),
- // Open Brace braces after control block
- rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 18 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], 8 /* InsertNewLine */, 1 /* CanDeleteNewLines */),
- // Open Brace braces after function
- // TypeScript: Function can have return types, which can be made of tons of different token kinds
- rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 18 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], 8 /* InsertNewLine */, 1 /* CanDeleteNewLines */),
- // Open Brace braces after TypeScript module/class/interface
- rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 18 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], 8 /* InsertNewLine */, 1 /* CanDeleteNewLines */),
- rule("SpaceAfterTypeAssertion", 31 /* GreaterThanToken */, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 4 /* InsertSpace */),
- rule("NoSpaceAfterTypeAssertion", 31 /* GreaterThanToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 16 /* DeleteSpace */),
- rule("SpaceBeforeTypeAnnotation", anyToken, 58 /* ColonToken */, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 4 /* InsertSpace */),
- rule("NoSpaceBeforeTypeAnnotation", anyToken, 58 /* ColonToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 16 /* DeleteSpace */),
- rule("NoOptionalSemicolon", 26 /* SemicolonToken */, anyTokenIncludingEOF, [optionEquals("semicolons", ts.SemicolonPreference.Remove), isSemicolonDeletionContext], 32 /* DeleteToken */),
- rule("OptionalSemicolon", anyToken, anyTokenIncludingEOF, [optionEquals("semicolons", ts.SemicolonPreference.Insert), isSemicolonInsertionContext], 64 /* InsertTrailingSemicolon */),
- ];
- // These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list.
- var lowPriorityCommonRules = [
- // Space after keyword but not before ; or : or ?
- rule("NoSpaceBeforeSemicolon", anyToken, 26 /* SemicolonToken */, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 18 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 4 /* InsertSpace */, 1 /* CanDeleteNewLines */),
- rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 18 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 4 /* InsertSpace */, 1 /* CanDeleteNewLines */),
- rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 18 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 4 /* InsertSpace */, 1 /* CanDeleteNewLines */),
- rule("NoSpaceBeforeComma", anyToken, 27 /* CommaToken */, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- // No space before and after indexer `x[]`
- rule("NoSpaceBeforeOpenBracket", anyTokenExcept(126 /* AsyncKeyword */, 78 /* CaseKeyword */), 22 /* OpenBracketToken */, [isNonJsxSameLineTokenContext], 16 /* DeleteSpace */),
- rule("NoSpaceAfterCloseBracket", 23 /* CloseBracketToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], 16 /* DeleteSpace */),
- rule("SpaceAfterSemicolon", 26 /* SemicolonToken */, anyToken, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- // Remove extra space between for and await
- rule("SpaceBetweenForAndAwaitKeyword", 93 /* ForKeyword */, 127 /* AwaitKeyword */, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- // Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
- // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
- rule("SpaceBetweenStatements", [21 /* CloseParenToken */, 86 /* DoKeyword */, 87 /* ElseKeyword */, 78 /* CaseKeyword */], anyToken, [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], 4 /* InsertSpace */),
- // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter.
- rule("SpaceAfterTryFinally", [107 /* TryKeyword */, 92 /* FinallyKeyword */], 18 /* OpenBraceToken */, [isNonJsxSameLineTokenContext], 4 /* InsertSpace */),
- ];
- return __spreadArrays(highPriorityCommonRules, userConfigurableRules, lowPriorityCommonRules);
- }
- formatting.getAllRules = getAllRules;
- /**
- * A rule takes a two tokens (left/right) and a particular context
- * for which you're meant to look at them. You then declare what should the
- * whitespace annotation be between these tokens via the action param.
- *
- * @param debugName Name to print
- * @param left The left side of the comparison
- * @param right The right side of the comparison
- * @param context A set of filters to narrow down the space in which this formatter rule applies
- * @param action a declaration of the expected whitespace
- * @param flags whether the rule deletes a line or not, defaults to no-op
- */
- function rule(debugName, left, right, context, action, flags) {
- if (flags === void 0) { flags = 0 /* None */; }
- return { leftTokenRange: toTokenRange(left), rightTokenRange: toTokenRange(right), rule: { debugName: debugName, context: context, action: action, flags: flags } };
- }
- function tokenRangeFrom(tokens) {
- return { tokens: tokens, isSpecific: true };
- }
- function toTokenRange(arg) {
- return typeof arg === "number" ? tokenRangeFrom([arg]) : ts.isArray(arg) ? tokenRangeFrom(arg) : arg;
- }
- function tokenRangeFromRange(from, to, except) {
- if (except === void 0) { except = []; }
- var tokens = [];
- for (var token = from; token <= to; token++) {
- if (!ts.contains(except, token)) {
- tokens.push(token);
- }
- }
- return tokenRangeFrom(tokens);
- }
- ///
- /// Contexts
- ///
- function optionEquals(optionName, optionValue) {
- return function (context) { return context.options && context.options[optionName] === optionValue; };
- }
- function isOptionEnabled(optionName) {
- return function (context) { return context.options && context.options.hasOwnProperty(optionName) && !!context.options[optionName]; };
- }
- function isOptionDisabled(optionName) {
- return function (context) { return context.options && context.options.hasOwnProperty(optionName) && !context.options[optionName]; };
- }
- function isOptionDisabledOrUndefined(optionName) {
- return function (context) { return !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName]; };
- }
- function isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName) {
- return function (context) { return !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName] || context.TokensAreOnSameLine(); };
- }
- function isOptionEnabledOrUndefined(optionName) {
- return function (context) { return !context.options || !context.options.hasOwnProperty(optionName) || !!context.options[optionName]; };
- }
- function isForContext(context) {
- return context.contextNode.kind === 230 /* ForStatement */;
- }
- function isNotForContext(context) {
- return !isForContext(context);
- }
- function isBinaryOpContext(context) {
- switch (context.contextNode.kind) {
- case 209 /* BinaryExpression */:
- return context.contextNode.operatorToken.kind !== 27 /* CommaToken */;
- case 210 /* ConditionalExpression */:
- case 180 /* ConditionalType */:
- case 217 /* AsExpression */:
- case 263 /* ExportSpecifier */:
- case 258 /* ImportSpecifier */:
- case 168 /* TypePredicate */:
- case 178 /* UnionType */:
- case 179 /* IntersectionType */:
- return true;
- // equals in binding elements: function foo([[x, y] = [1, 2]])
- case 191 /* BindingElement */:
- // equals in type X = ...
- // falls through
- case 247 /* TypeAliasDeclaration */:
- // equal in import a = module('a');
- // falls through
- case 253 /* ImportEqualsDeclaration */:
- // equal in let a = 0
- // falls through
- case 242 /* VariableDeclaration */:
- // equal in p = 0
- // falls through
- case 156 /* Parameter */:
- case 284 /* EnumMember */:
- case 159 /* PropertyDeclaration */:
- case 158 /* PropertySignature */:
- return context.currentTokenSpan.kind === 62 /* EqualsToken */ || context.nextTokenSpan.kind === 62 /* EqualsToken */;
- // "in" keyword in for (let x in []) { }
- case 231 /* ForInStatement */:
- // "in" keyword in [P in keyof T]: T[P]
- // falls through
- case 155 /* TypeParameter */:
- return context.currentTokenSpan.kind === 97 /* InKeyword */ || context.nextTokenSpan.kind === 97 /* InKeyword */ || context.currentTokenSpan.kind === 62 /* EqualsToken */ || context.nextTokenSpan.kind === 62 /* EqualsToken */;
- // Technically, "of" is not a binary operator, but format it the same way as "in"
- case 232 /* ForOfStatement */:
- return context.currentTokenSpan.kind === 152 /* OfKeyword */ || context.nextTokenSpan.kind === 152 /* OfKeyword */;
- }
- return false;
- }
- function isNotBinaryOpContext(context) {
- return !isBinaryOpContext(context);
- }
- function isNotTypeAnnotationContext(context) {
- return !isTypeAnnotationContext(context);
- }
- function isTypeAnnotationContext(context) {
- var contextKind = context.contextNode.kind;
- return contextKind === 159 /* PropertyDeclaration */ ||
- contextKind === 158 /* PropertySignature */ ||
- contextKind === 156 /* Parameter */ ||
- contextKind === 242 /* VariableDeclaration */ ||
- ts.isFunctionLikeKind(contextKind);
- }
- function isConditionalOperatorContext(context) {
- return context.contextNode.kind === 210 /* ConditionalExpression */ ||
- context.contextNode.kind === 180 /* ConditionalType */;
- }
- function isSameLineTokenOrBeforeBlockContext(context) {
- return context.TokensAreOnSameLine() || isBeforeBlockContext(context);
- }
- function isBraceWrappedContext(context) {
- return context.contextNode.kind === 189 /* ObjectBindingPattern */ ||
- context.contextNode.kind === 186 /* MappedType */ ||
- isSingleLineBlockContext(context);
- }
- // This check is done before an open brace in a control construct, a function, or a typescript block declaration
- function isBeforeMultilineBlockContext(context) {
- return isBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine());
- }
- function isMultilineBlockContext(context) {
- return isBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
- }
- function isSingleLineBlockContext(context) {
- return isBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
- }
- function isBlockContext(context) {
- return nodeIsBlockContext(context.contextNode);
- }
- function isBeforeBlockContext(context) {
- return nodeIsBlockContext(context.nextTokenParent);
- }
- // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children
- function nodeIsBlockContext(node) {
- if (nodeIsTypeScriptDeclWithBlockContext(node)) {
- // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc).
- return true;
- }
- switch (node.kind) {
- case 223 /* Block */:
- case 251 /* CaseBlock */:
- case 193 /* ObjectLiteralExpression */:
- case 250 /* ModuleBlock */:
- return true;
- }
- return false;
- }
- function isFunctionDeclContext(context) {
- switch (context.contextNode.kind) {
- case 244 /* FunctionDeclaration */:
- case 161 /* MethodDeclaration */:
- case 160 /* MethodSignature */:
- // case SyntaxKind.MemberFunctionDeclaration:
- // falls through
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- // case SyntaxKind.MethodSignature:
- // falls through
- case 165 /* CallSignature */:
- case 201 /* FunctionExpression */:
- case 162 /* Constructor */:
- case 202 /* ArrowFunction */:
- // case SyntaxKind.ConstructorDeclaration:
- // case SyntaxKind.SimpleArrowFunctionExpression:
- // case SyntaxKind.ParenthesizedArrowFunctionExpression:
- // falls through
- case 246 /* InterfaceDeclaration */: // This one is not truly a function, but for formatting purposes, it acts just like one
- return true;
- }
- return false;
- }
- function isNotFunctionDeclContext(context) {
- return !isFunctionDeclContext(context);
- }
- function isFunctionDeclarationOrFunctionExpressionContext(context) {
- return context.contextNode.kind === 244 /* FunctionDeclaration */ || context.contextNode.kind === 201 /* FunctionExpression */;
- }
- function isTypeScriptDeclWithBlockContext(context) {
- return nodeIsTypeScriptDeclWithBlockContext(context.contextNode);
- }
- function nodeIsTypeScriptDeclWithBlockContext(node) {
- switch (node.kind) {
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 246 /* InterfaceDeclaration */:
- case 248 /* EnumDeclaration */:
- case 173 /* TypeLiteral */:
- case 249 /* ModuleDeclaration */:
- case 260 /* ExportDeclaration */:
- case 261 /* NamedExports */:
- case 254 /* ImportDeclaration */:
- case 257 /* NamedImports */:
- return true;
- }
- return false;
- }
- function isAfterCodeBlockContext(context) {
- switch (context.currentTokenParent.kind) {
- case 245 /* ClassDeclaration */:
- case 249 /* ModuleDeclaration */:
- case 248 /* EnumDeclaration */:
- case 280 /* CatchClause */:
- case 250 /* ModuleBlock */:
- case 237 /* SwitchStatement */:
- return true;
- case 223 /* Block */: {
- var blockParent = context.currentTokenParent.parent;
- // In a codefix scenario, we can't rely on parents being set. So just always return true.
- if (!blockParent || blockParent.kind !== 202 /* ArrowFunction */ && blockParent.kind !== 201 /* FunctionExpression */) {
- return true;
- }
- }
- }
- return false;
- }
- function isControlDeclContext(context) {
- switch (context.contextNode.kind) {
- case 227 /* IfStatement */:
- case 237 /* SwitchStatement */:
- case 230 /* ForStatement */:
- case 231 /* ForInStatement */:
- case 232 /* ForOfStatement */:
- case 229 /* WhileStatement */:
- case 240 /* TryStatement */:
- case 228 /* DoStatement */:
- case 236 /* WithStatement */:
- // TODO
- // case SyntaxKind.ElseClause:
- // falls through
- case 280 /* CatchClause */:
- return true;
- default:
- return false;
- }
- }
- function isObjectContext(context) {
- return context.contextNode.kind === 193 /* ObjectLiteralExpression */;
- }
- function isFunctionCallContext(context) {
- return context.contextNode.kind === 196 /* CallExpression */;
- }
- function isNewContext(context) {
- return context.contextNode.kind === 197 /* NewExpression */;
- }
- function isFunctionCallOrNewContext(context) {
- return isFunctionCallContext(context) || isNewContext(context);
- }
- function isPreviousTokenNotComma(context) {
- return context.currentTokenSpan.kind !== 27 /* CommaToken */;
- }
- function isNextTokenNotCloseBracket(context) {
- return context.nextTokenSpan.kind !== 23 /* CloseBracketToken */;
- }
- function isNextTokenNotCloseParen(context) {
- return context.nextTokenSpan.kind !== 21 /* CloseParenToken */;
- }
- function isArrowFunctionContext(context) {
- return context.contextNode.kind === 202 /* ArrowFunction */;
- }
- function isImportTypeContext(context) {
- return context.contextNode.kind === 188 /* ImportType */;
- }
- function isNonJsxSameLineTokenContext(context) {
- return context.TokensAreOnSameLine() && context.contextNode.kind !== 11 /* JsxText */;
- }
- function isNonJsxElementOrFragmentContext(context) {
- return context.contextNode.kind !== 266 /* JsxElement */ && context.contextNode.kind !== 270 /* JsxFragment */;
- }
- function isJsxExpressionContext(context) {
- return context.contextNode.kind === 276 /* JsxExpression */ || context.contextNode.kind === 275 /* JsxSpreadAttribute */;
- }
- function isNextTokenParentJsxAttribute(context) {
- return context.nextTokenParent.kind === 273 /* JsxAttribute */;
- }
- function isJsxAttributeContext(context) {
- return context.contextNode.kind === 273 /* JsxAttribute */;
- }
- function isJsxSelfClosingElementContext(context) {
- return context.contextNode.kind === 267 /* JsxSelfClosingElement */;
- }
- function isNotBeforeBlockInFunctionDeclarationContext(context) {
- return !isFunctionDeclContext(context) && !isBeforeBlockContext(context);
- }
- function isEndOfDecoratorContextOnSameLine(context) {
- return context.TokensAreOnSameLine() &&
- !!context.contextNode.decorators &&
- nodeIsInDecoratorContext(context.currentTokenParent) &&
- !nodeIsInDecoratorContext(context.nextTokenParent);
- }
- function nodeIsInDecoratorContext(node) {
- while (ts.isExpressionNode(node)) {
- node = node.parent;
- }
- return node.kind === 157 /* Decorator */;
- }
- function isStartOfVariableDeclarationList(context) {
- return context.currentTokenParent.kind === 243 /* VariableDeclarationList */ &&
- context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos;
- }
- function isNotFormatOnEnter(context) {
- return context.formattingRequestKind !== 2 /* FormatOnEnter */;
- }
- function isModuleDeclContext(context) {
- return context.contextNode.kind === 249 /* ModuleDeclaration */;
- }
- function isObjectTypeContext(context) {
- return context.contextNode.kind === 173 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration;
- }
- function isConstructorSignatureContext(context) {
- return context.contextNode.kind === 166 /* ConstructSignature */;
- }
- function isTypeArgumentOrParameterOrAssertion(token, parent) {
- if (token.kind !== 29 /* LessThanToken */ && token.kind !== 31 /* GreaterThanToken */) {
- return false;
- }
- switch (parent.kind) {
- case 169 /* TypeReference */:
- case 199 /* TypeAssertionExpression */:
- case 247 /* TypeAliasDeclaration */:
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 246 /* InterfaceDeclaration */:
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 202 /* ArrowFunction */:
- case 161 /* MethodDeclaration */:
- case 160 /* MethodSignature */:
- case 165 /* CallSignature */:
- case 166 /* ConstructSignature */:
- case 196 /* CallExpression */:
- case 197 /* NewExpression */:
- case 216 /* ExpressionWithTypeArguments */:
- return true;
- default:
- return false;
- }
- }
- function isTypeArgumentOrParameterOrAssertionContext(context) {
- return isTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) ||
- isTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent);
- }
- function isTypeAssertionContext(context) {
- return context.contextNode.kind === 199 /* TypeAssertionExpression */;
- }
- function isVoidOpContext(context) {
- return context.currentTokenSpan.kind === 110 /* VoidKeyword */ && context.currentTokenParent.kind === 205 /* VoidExpression */;
- }
- function isYieldOrYieldStarWithOperand(context) {
- return context.contextNode.kind === 212 /* YieldExpression */ && context.contextNode.expression !== undefined;
- }
- function isNonNullAssertionContext(context) {
- return context.contextNode.kind === 218 /* NonNullExpression */;
- }
- function isNotStatementConditionContext(context) {
- return !isStatementConditionContext(context);
- }
- function isStatementConditionContext(context) {
- switch (context.contextNode.kind) {
- case 227 /* IfStatement */:
- case 230 /* ForStatement */:
- case 231 /* ForInStatement */:
- case 232 /* ForOfStatement */:
- case 228 /* DoStatement */:
- case 229 /* WhileStatement */:
- return true;
- default:
- return false;
- }
- }
- function isSemicolonDeletionContext(context) {
- var nextTokenKind = context.nextTokenSpan.kind;
- var nextTokenStart = context.nextTokenSpan.pos;
- if (ts.isTrivia(nextTokenKind)) {
- var nextRealToken = context.nextTokenParent === context.currentTokenParent
- ? ts.findNextToken(context.currentTokenParent, ts.findAncestor(context.currentTokenParent, function (a) { return !a.parent; }), context.sourceFile)
- : context.nextTokenParent.getFirstToken(context.sourceFile);
- if (!nextRealToken) {
- return true;
- }
- nextTokenKind = nextRealToken.kind;
- nextTokenStart = nextRealToken.getStart(context.sourceFile);
- }
- var startLine = context.sourceFile.getLineAndCharacterOfPosition(context.currentTokenSpan.pos).line;
- var endLine = context.sourceFile.getLineAndCharacterOfPosition(nextTokenStart).line;
- if (startLine === endLine) {
- return nextTokenKind === 19 /* CloseBraceToken */
- || nextTokenKind === 1 /* EndOfFileToken */;
- }
- if (nextTokenKind === 222 /* SemicolonClassElement */ ||
- nextTokenKind === 26 /* SemicolonToken */) {
- return false;
- }
- if (context.contextNode.kind === 246 /* InterfaceDeclaration */ ||
- context.contextNode.kind === 247 /* TypeAliasDeclaration */) {
- // Can’t remove semicolon after `foo`; it would parse as a method declaration:
- //
- // interface I {
- // foo;
- // (): void
- // }
- return !ts.isPropertySignature(context.currentTokenParent)
- || !!context.currentTokenParent.type
- || nextTokenKind !== 20 /* OpenParenToken */;
- }
- if (ts.isPropertyDeclaration(context.currentTokenParent)) {
- return !context.currentTokenParent.initializer;
- }
- return context.currentTokenParent.kind !== 230 /* ForStatement */
- && context.currentTokenParent.kind !== 224 /* EmptyStatement */
- && context.currentTokenParent.kind !== 222 /* SemicolonClassElement */
- && nextTokenKind !== 22 /* OpenBracketToken */
- && nextTokenKind !== 20 /* OpenParenToken */
- && nextTokenKind !== 39 /* PlusToken */
- && nextTokenKind !== 40 /* MinusToken */
- && nextTokenKind !== 43 /* SlashToken */
- && nextTokenKind !== 13 /* RegularExpressionLiteral */
- && nextTokenKind !== 27 /* CommaToken */
- && nextTokenKind !== 211 /* TemplateExpression */
- && nextTokenKind !== 15 /* TemplateHead */
- && nextTokenKind !== 14 /* NoSubstitutionTemplateLiteral */
- && nextTokenKind !== 24 /* DotToken */;
- }
- function isSemicolonInsertionContext(context) {
- return ts.positionIsASICandidate(context.currentTokenSpan.end, context.currentTokenParent, context.sourceFile);
- }
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- function getFormatContext(options, host) {
- return { options: options, getRules: getRulesMap(), host: host };
- }
- formatting.getFormatContext = getFormatContext;
- var rulesMapCache;
- function getRulesMap() {
- if (rulesMapCache === undefined) {
- rulesMapCache = createRulesMap(formatting.getAllRules());
- }
- return rulesMapCache;
- }
- /**
- * For a given rule action, gets a mask of other rule actions that
- * cannot be applied at the same position.
- */
- function getRuleActionExclusion(ruleAction) {
- var mask = 0;
- if (ruleAction & 1 /* StopProcessingSpaceActions */) {
- mask |= 28 /* ModifySpaceAction */;
- }
- if (ruleAction & 2 /* StopProcessingTokenActions */) {
- mask |= 96 /* ModifyTokenAction */;
- }
- if (ruleAction & 28 /* ModifySpaceAction */) {
- mask |= 28 /* ModifySpaceAction */;
- }
- if (ruleAction & 96 /* ModifyTokenAction */) {
- mask |= 96 /* ModifyTokenAction */;
- }
- return mask;
- }
- function createRulesMap(rules) {
- var map = buildMap(rules);
- return function (context) {
- var bucket = map[getRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind)];
- if (bucket) {
- var rules_1 = [];
- var ruleActionMask = 0;
- for (var _i = 0, bucket_1 = bucket; _i < bucket_1.length; _i++) {
- var rule = bucket_1[_i];
- var acceptRuleActions = ~getRuleActionExclusion(ruleActionMask);
- if (rule.action & acceptRuleActions && ts.every(rule.context, function (c) { return c(context); })) {
- rules_1.push(rule);
- ruleActionMask |= rule.action;
- }
- }
- if (rules_1.length) {
- return rules_1;
- }
- }
- };
- }
- function buildMap(rules) {
- // Map from bucket index to array of rules
- var map = new Array(mapRowLength * mapRowLength);
- // This array is used only during construction of the rulesbucket in the map
- var rulesBucketConstructionStateList = new Array(map.length);
- for (var _i = 0, rules_2 = rules; _i < rules_2.length; _i++) {
- var rule = rules_2[_i];
- var specificRule = rule.leftTokenRange.isSpecific && rule.rightTokenRange.isSpecific;
- for (var _a = 0, _b = rule.leftTokenRange.tokens; _a < _b.length; _a++) {
- var left = _b[_a];
- for (var _c = 0, _d = rule.rightTokenRange.tokens; _c < _d.length; _c++) {
- var right = _d[_c];
- var index = getRuleBucketIndex(left, right);
- var rulesBucket = map[index];
- if (rulesBucket === undefined) {
- rulesBucket = map[index] = [];
- }
- addRule(rulesBucket, rule.rule, specificRule, rulesBucketConstructionStateList, index);
- }
- }
- }
- return map;
- }
- function getRuleBucketIndex(row, column) {
- ts.Debug.assert(row <= 152 /* LastKeyword */ && column <= 152 /* LastKeyword */, "Must compute formatting context from tokens");
- return (row * mapRowLength) + column;
- }
- var maskBitSize = 5;
- var mask = 31; // MaskBitSize bits
- var mapRowLength = 152 /* LastToken */ + 1;
- var RulesPosition;
- (function (RulesPosition) {
- RulesPosition[RulesPosition["StopRulesSpecific"] = 0] = "StopRulesSpecific";
- RulesPosition[RulesPosition["StopRulesAny"] = maskBitSize * 1] = "StopRulesAny";
- RulesPosition[RulesPosition["ContextRulesSpecific"] = maskBitSize * 2] = "ContextRulesSpecific";
- RulesPosition[RulesPosition["ContextRulesAny"] = maskBitSize * 3] = "ContextRulesAny";
- RulesPosition[RulesPosition["NoContextRulesSpecific"] = maskBitSize * 4] = "NoContextRulesSpecific";
- RulesPosition[RulesPosition["NoContextRulesAny"] = maskBitSize * 5] = "NoContextRulesAny";
- })(RulesPosition || (RulesPosition = {}));
- // The Rules list contains all the inserted rules into a rulebucket in the following order:
- // 1- Ignore rules with specific token combination
- // 2- Ignore rules with any token combination
- // 3- Context rules with specific token combination
- // 4- Context rules with any token combination
- // 5- Non-context rules with specific token combination
- // 6- Non-context rules with any token combination
- //
- // The member rulesInsertionIndexBitmap is used to describe the number of rules
- // in each sub-bucket (above) hence can be used to know the index of where to insert
- // the next rule. It's a bitmap which contains 6 different sections each is given 5 bits.
- //
- // Example:
- // In order to insert a rule to the end of sub-bucket (3), we get the index by adding
- // the values in the bitmap segments 3rd, 2nd, and 1st.
- function addRule(rules, rule, specificTokens, constructionState, rulesBucketIndex) {
- var position = rule.action & 3 /* StopAction */ ?
- specificTokens ? RulesPosition.StopRulesSpecific : RulesPosition.StopRulesAny :
- rule.context !== formatting.anyContext ?
- specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny :
- specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny;
- var state = constructionState[rulesBucketIndex] || 0;
- rules.splice(getInsertionIndex(state, position), 0, rule);
- constructionState[rulesBucketIndex] = increaseInsertionIndex(state, position);
- }
- function getInsertionIndex(indexBitmap, maskPosition) {
- var index = 0;
- for (var pos = 0; pos <= maskPosition; pos += maskBitSize) {
- index += indexBitmap & mask;
- indexBitmap >>= maskBitSize;
- }
- return index;
- }
- function increaseInsertionIndex(indexBitmap, maskPosition) {
- var value = ((indexBitmap >> maskPosition) & mask) + 1;
- ts.Debug.assert((value & mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
- return (indexBitmap & ~(mask << maskPosition)) | (value << maskPosition);
- }
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- function createTextRangeWithKind(pos, end, kind) {
- var textRangeWithKind = { pos: pos, end: end, kind: kind };
- if (ts.Debug.isDebugging) {
- Object.defineProperty(textRangeWithKind, "__debugKind", {
- get: function () { return ts.Debug.formatSyntaxKind(kind); },
- });
- }
- return textRangeWithKind;
- }
- formatting.createTextRangeWithKind = createTextRangeWithKind;
- var Constants;
- (function (Constants) {
- Constants[Constants["Unknown"] = -1] = "Unknown";
- })(Constants || (Constants = {}));
- function formatOnEnter(position, sourceFile, formatContext) {
- var line = sourceFile.getLineAndCharacterOfPosition(position).line;
- if (line === 0) {
- return [];
- }
- // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters.
- // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as
- // trailing whitespaces. So the end of the formatting span should be the later one between:
- // 1. the end of the previous line
- // 2. the last non-whitespace character in the current line
- var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile);
- while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) {
- endOfFormatSpan--;
- }
- // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to
- // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the
- // previous character before the end of format span is line break character as well.
- if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) {
- endOfFormatSpan--;
- }
- var span = {
- // get start position for the previous line
- pos: ts.getStartPositionOfLine(line - 1, sourceFile),
- // end value is exclusive so add 1 to the result
- end: endOfFormatSpan + 1
- };
- return formatSpan(span, sourceFile, formatContext, 2 /* FormatOnEnter */);
- }
- formatting.formatOnEnter = formatOnEnter;
- function formatOnSemicolon(position, sourceFile, formatContext) {
- var semicolon = findImmediatelyPrecedingTokenOfKind(position, 26 /* SemicolonToken */, sourceFile);
- return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, 3 /* FormatOnSemicolon */);
- }
- formatting.formatOnSemicolon = formatOnSemicolon;
- function formatOnOpeningCurly(position, sourceFile, formatContext) {
- var openingCurly = findImmediatelyPrecedingTokenOfKind(position, 18 /* OpenBraceToken */, sourceFile);
- if (!openingCurly) {
- return [];
- }
- var curlyBraceRange = openingCurly.parent;
- var outermostNode = findOutermostNodeWithinListLevel(curlyBraceRange);
- /**
- * We limit the span to end at the opening curly to handle the case where
- * the brace matched to that just typed will be incorrect after further edits.
- * For example, we could type the opening curly for the following method
- * body without brace-matching activated:
- * ```
- * class C {
- * foo()
- * }
- * ```
- * and we wouldn't want to move the closing brace.
- */
- var textRange = {
- pos: ts.getLineStartPositionForPosition(outermostNode.getStart(sourceFile), sourceFile),
- end: position
- };
- return formatSpan(textRange, sourceFile, formatContext, 4 /* FormatOnOpeningCurlyBrace */);
- }
- formatting.formatOnOpeningCurly = formatOnOpeningCurly;
- function formatOnClosingCurly(position, sourceFile, formatContext) {
- var precedingToken = findImmediatelyPrecedingTokenOfKind(position, 19 /* CloseBraceToken */, sourceFile);
- return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, 5 /* FormatOnClosingCurlyBrace */);
- }
- formatting.formatOnClosingCurly = formatOnClosingCurly;
- function formatDocument(sourceFile, formatContext) {
- var span = {
- pos: 0,
- end: sourceFile.text.length
- };
- return formatSpan(span, sourceFile, formatContext, 0 /* FormatDocument */);
- }
- formatting.formatDocument = formatDocument;
- function formatSelection(start, end, sourceFile, formatContext) {
- // format from the beginning of the line
- var span = {
- pos: ts.getLineStartPositionForPosition(start, sourceFile),
- end: end,
- };
- return formatSpan(span, sourceFile, formatContext, 1 /* FormatSelection */);
- }
- formatting.formatSelection = formatSelection;
- /**
- * Validating `expectedTokenKind` ensures the token was typed in the context we expect (eg: not a comment).
- * @param expectedTokenKind The kind of the last token constituting the desired parent node.
- */
- function findImmediatelyPrecedingTokenOfKind(end, expectedTokenKind, sourceFile) {
- var precedingToken = ts.findPrecedingToken(end, sourceFile);
- return precedingToken && precedingToken.kind === expectedTokenKind && end === precedingToken.getEnd() ?
- precedingToken :
- undefined;
- }
- /**
- * Finds the highest node enclosing `node` at the same list level as `node`
- * and whose end does not exceed `node.end`.
- *
- * Consider typing the following
- * ```
- * let x = 1;
- * while (true) {
- * }
- * ```
- * Upon typing the closing curly, we want to format the entire `while`-statement, but not the preceding
- * variable declaration.
- */
- function findOutermostNodeWithinListLevel(node) {
- var current = node;
- while (current &&
- current.parent &&
- current.parent.end === node.end &&
- !isListElement(current.parent, current)) {
- current = current.parent;
- }
- return current;
- }
- // Returns true if node is a element in some list in parent
- // i.e. parent is class declaration with the list of members and node is one of members.
- function isListElement(parent, node) {
- switch (parent.kind) {
- case 245 /* ClassDeclaration */:
- case 246 /* InterfaceDeclaration */:
- return ts.rangeContainsRange(parent.members, node);
- case 249 /* ModuleDeclaration */:
- var body = parent.body;
- return !!body && body.kind === 250 /* ModuleBlock */ && ts.rangeContainsRange(body.statements, node);
- case 290 /* SourceFile */:
- case 223 /* Block */:
- case 250 /* ModuleBlock */:
- return ts.rangeContainsRange(parent.statements, node);
- case 280 /* CatchClause */:
- return ts.rangeContainsRange(parent.block.statements, node);
- }
- return false;
- }
- /** find node that fully contains given text range */
- function findEnclosingNode(range, sourceFile) {
- return find(sourceFile);
- function find(n) {
- var candidate = ts.forEachChild(n, function (c) { return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c; });
- if (candidate) {
- var result = find(candidate);
- if (result) {
- return result;
- }
- }
- return n;
- }
- }
- /** formatting is not applied to ranges that contain parse errors.
- * This function will return a predicate that for a given text range will tell
- * if there are any parse errors that overlap with the range.
- */
- function prepareRangeContainsErrorFunction(errors, originalRange) {
- if (!errors.length) {
- return rangeHasNoErrors;
- }
- // pick only errors that fall in range
- var sorted = errors
- .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); }) // TODO: GH#18217
- .sort(function (e1, e2) { return e1.start - e2.start; });
- if (!sorted.length) {
- return rangeHasNoErrors;
- }
- var index = 0;
- return function (r) {
- // in current implementation sequence of arguments [r1, r2...] is monotonically increasing.
- // 'index' tracks the index of the most recent error that was checked.
- while (true) {
- if (index >= sorted.length) {
- // all errors in the range were already checked -> no error in specified range
- return false;
- }
- var error = sorted[index];
- if (r.end <= error.start) {
- // specified range ends before the error referred by 'index' - no error in range
- return false;
- }
- if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) {
- // specified range overlaps with error range
- return true;
- }
- index++;
- }
- };
- function rangeHasNoErrors() {
- return false;
- }
- }
- /**
- * Start of the original range might fall inside the comment - scanner will not yield appropriate results
- * This function will look for token that is located before the start of target range
- * and return its end as start position for the scanner.
- */
- function getScanStartPosition(enclosingNode, originalRange, sourceFile) {
- var start = enclosingNode.getStart(sourceFile);
- if (start === originalRange.pos && enclosingNode.end === originalRange.end) {
- return start;
- }
- var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile);
- if (!precedingToken) {
- // no preceding token found - start from the beginning of enclosing node
- return enclosingNode.pos;
- }
- // preceding token ends after the start of original range (i.e when originalRange.pos falls in the middle of literal)
- // start from the beginning of enclosingNode to handle the entire 'originalRange'
- if (precedingToken.end >= originalRange.pos) {
- return enclosingNode.pos;
- }
- return precedingToken.end;
- }
- /*
- * For cases like
- * if (a ||
- * b ||$
- * c) {...}
- * If we hit Enter at $ we want line ' b ||' to be indented.
- * Formatting will be applied to the last two lines.
- * Node that fully encloses these lines is binary expression 'a ||...'.
- * Initial indentation for this node will be 0.
- * Binary expressions don't introduce new indentation scopes, however it is possible
- * that some parent node on the same line does - like if statement in this case.
- * Note that we are considering parents only from the same line with initial node -
- * if parent is on the different line - its delta was already contributed
- * to the initial indentation.
- */
- function getOwnOrInheritedDelta(n, options, sourceFile) {
- var previousLine = -1 /* Unknown */;
- var child;
- while (n) {
- var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
- if (previousLine !== -1 /* Unknown */ && line !== previousLine) {
- break;
- }
- if (formatting.SmartIndenter.shouldIndentChildNode(options, n, child, sourceFile)) {
- return options.indentSize;
- }
- previousLine = line;
- child = n;
- n = n.parent;
- }
- return 0;
- }
- function formatNodeGivenIndentation(node, sourceFileLike, languageVariant, initialIndentation, delta, formatContext) {
- var range = { pos: 0, end: sourceFileLike.text.length };
- return formatting.getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, function (scanner) { return formatSpanWorker(range, node, initialIndentation, delta, scanner, formatContext, 1 /* FormatSelection */, function (_) { return false; }, // assume that node does not have any errors
- sourceFileLike); });
- }
- formatting.formatNodeGivenIndentation = formatNodeGivenIndentation;
- function formatNodeLines(node, sourceFile, formatContext, requestKind) {
- if (!node) {
- return [];
- }
- var span = {
- pos: ts.getLineStartPositionForPosition(node.getStart(sourceFile), sourceFile),
- end: node.end
- };
- return formatSpan(span, sourceFile, formatContext, requestKind);
- }
- function formatSpan(originalRange, sourceFile, formatContext, requestKind) {
- // find the smallest node that fully wraps the range and compute the initial indentation for the node
- var enclosingNode = findEnclosingNode(originalRange, sourceFile);
- return formatting.getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, function (scanner) { return formatSpanWorker(originalRange, enclosingNode, formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile); });
- }
- function formatSpanWorker(originalRange, enclosingNode, initialIndentation, delta, formattingScanner, _a, requestKind, rangeContainsError, sourceFile) {
- var options = _a.options, getRules = _a.getRules, host = _a.host;
- // formatting context is used by rules provider
- var formattingContext = new formatting.FormattingContext(sourceFile, requestKind, options);
- var previousRange;
- var previousParent;
- var previousRangeStartLine;
- var lastIndentedLine;
- var indentationOnLastIndentedLine = -1 /* Unknown */;
- var edits = [];
- formattingScanner.advance();
- if (formattingScanner.isOnToken()) {
- var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line;
- var undecoratedStartLine = startLine;
- if (enclosingNode.decorators) {
- undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line;
- }
- processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta);
- }
- if (!formattingScanner.isOnToken()) {
- var leadingTrivia = formattingScanner.getCurrentLeadingTrivia();
- if (leadingTrivia) {
- indentTriviaItems(leadingTrivia, initialIndentation, /*indentNextTokenOrTrivia*/ false, function (item) { return processRange(item, sourceFile.getLineAndCharacterOfPosition(item.pos), enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined); });
- if (options.trimTrailingWhitespace !== false) {
- trimTrailingWhitespacesForRemainingRange();
- }
- }
- }
- return edits;
- // local functions
- /** Tries to compute the indentation for a list element.
- * If list element is not in range then
- * function will pick its actual indentation
- * so it can be pushed downstream as inherited indentation.
- * If list element is in the range - its indentation will be equal
- * to inherited indentation from its predecessors.
- */
- function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) {
- if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) ||
- ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) {
- if (inheritedIndentation !== -1 /* Unknown */) {
- return inheritedIndentation;
- }
- }
- else {
- var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line;
- var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile);
- var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options);
- if (startLine !== parentStartLine || startPos === column) {
- // Use the base indent size if it is greater than
- // the indentation of the inherited predecessor.
- var baseIndentSize = formatting.SmartIndenter.getBaseIndentation(options);
- return baseIndentSize > column ? baseIndentSize : column;
- }
- }
- return -1 /* Unknown */;
- }
- function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) {
- var delta = formatting.SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0;
- if (effectiveParentStartLine === startLine) {
- // if node is located on the same line with the parent
- // - inherit indentation from the parent
- // - push children if either parent of node itself has non-zero delta
- return {
- indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine : parentDynamicIndentation.getIndentation(),
- delta: Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta)
- };
- }
- else if (inheritedIndentation === -1 /* Unknown */) {
- if (node.kind === 20 /* OpenParenToken */ && startLine === lastIndentedLine) {
- // the is used for chaining methods formatting
- // - we need to get the indentation on last line and the delta of parent
- return { indentation: indentationOnLastIndentedLine, delta: parentDynamicIndentation.getDelta(node) };
- }
- else if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
- return { indentation: parentDynamicIndentation.getIndentation(), delta: delta };
- }
- else if (formatting.SmartIndenter.argumentStartsOnSameLineAsPreviousArgument(parent, node, startLine, sourceFile)) {
- return { indentation: parentDynamicIndentation.getIndentation(), delta: delta };
- }
- else {
- return { indentation: parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node), delta: delta };
- }
- }
- else {
- return { indentation: inheritedIndentation, delta: delta };
- }
- }
- function getFirstNonDecoratorTokenOfNode(node) {
- if (node.modifiers && node.modifiers.length) {
- return node.modifiers[0].kind;
- }
- switch (node.kind) {
- case 245 /* ClassDeclaration */: return 80 /* ClassKeyword */;
- case 246 /* InterfaceDeclaration */: return 114 /* InterfaceKeyword */;
- case 244 /* FunctionDeclaration */: return 94 /* FunctionKeyword */;
- case 248 /* EnumDeclaration */: return 248 /* EnumDeclaration */;
- case 163 /* GetAccessor */: return 131 /* GetKeyword */;
- case 164 /* SetAccessor */: return 142 /* SetKeyword */;
- case 161 /* MethodDeclaration */:
- if (node.asteriskToken) {
- return 41 /* AsteriskToken */;
- }
- // falls through
- case 159 /* PropertyDeclaration */:
- case 156 /* Parameter */:
- var name = ts.getNameOfDeclaration(node);
- if (name) {
- return name.kind;
- }
- }
- }
- function getDynamicIndentation(node, nodeStartLine, indentation, delta) {
- return {
- getIndentationForComment: function (kind, tokenIndentation, container) {
- switch (kind) {
- // preceding comment to the token that closes the indentation scope inherits the indentation from the scope
- // .. {
- // // comment
- // }
- case 19 /* CloseBraceToken */:
- case 23 /* CloseBracketToken */:
- case 21 /* CloseParenToken */:
- return indentation + getDelta(container);
- }
- return tokenIndentation !== -1 /* Unknown */ ? tokenIndentation : indentation;
- },
- // if list end token is LessThanToken '>' then its delta should be explicitly suppressed
- // so that LessThanToken as a binary operator can still be indented.
- // foo.then
- // <
- // number,
- // string,
- // >();
- // vs
- // var a = xValue
- // > yValue;
- getIndentationForToken: function (line, kind, container, suppressDelta) {
- return !suppressDelta && shouldAddDelta(line, kind, container) ? indentation + getDelta(container) : indentation;
- },
- getIndentation: function () { return indentation; },
- getDelta: getDelta,
- recomputeIndentation: function (lineAdded, parent) {
- if (formatting.SmartIndenter.shouldIndentChildNode(options, parent, node, sourceFile)) {
- indentation += lineAdded ? options.indentSize : -options.indentSize;
- delta = formatting.SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize : 0;
- }
- }
- };
- function shouldAddDelta(line, kind, container) {
- switch (kind) {
- // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent
- case 18 /* OpenBraceToken */:
- case 19 /* CloseBraceToken */:
- case 21 /* CloseParenToken */:
- case 87 /* ElseKeyword */:
- case 111 /* WhileKeyword */:
- case 59 /* AtToken */:
- return false;
- case 43 /* SlashToken */:
- case 31 /* GreaterThanToken */:
- switch (container.kind) {
- case 268 /* JsxOpeningElement */:
- case 269 /* JsxClosingElement */:
- case 267 /* JsxSelfClosingElement */:
- return false;
- }
- break;
- case 22 /* OpenBracketToken */:
- case 23 /* CloseBracketToken */:
- if (container.kind !== 186 /* MappedType */) {
- return false;
- }
- break;
- }
- // if token line equals to the line of containing node (this is a first token in the node) - use node indentation
- return nodeStartLine !== line
- // if this token is the first token following the list of decorators, we do not need to indent
- && !(node.decorators && kind === getFirstNonDecoratorTokenOfNode(node));
- }
- function getDelta(child) {
- // Delta value should be zero when the node explicitly prevents indentation of the child node
- return formatting.SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0;
- }
- }
- function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) {
- if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) {
- return;
- }
- var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta);
- // a useful observations when tracking context node
- // /
- // [a]
- // / | \
- // [b] [c] [d]
- // node 'a' is a context node for nodes 'b', 'c', 'd'
- // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a'
- // this rule can be applied recursively to child nodes of 'a'.
- //
- // context node is set to parent node value after processing every child node
- // context node is set to parent of the token after processing every token
- var childContextNode = contextNode;
- // if there are any tokens that logically belong to node and interleave child nodes
- // such tokens will be consumed in processChildNode for the child that follows them
- ts.forEachChild(node, function (child) {
- processChildNode(child, /*inheritedIndentation*/ -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false);
- }, function (nodes) {
- processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation);
- });
- // proceed any tokens in the node that are located after child nodes
- while (formattingScanner.isOnToken()) {
- var tokenInfo = formattingScanner.readTokenInfo(node);
- if (tokenInfo.token.end > node.end) {
- break;
- }
- if (node.kind === 11 /* JsxText */) {
- // Intentation rules for jsx text are handled by `indentMultilineCommentOrJsxText` inside `processChildNode`; just fastforward past it here
- formattingScanner.advance();
- continue;
- }
- consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation, node);
- }
- if (!node.parent && formattingScanner.isOnEOF()) {
- var token = formattingScanner.readEOFTokenRange();
- if (token.end <= node.end && previousRange) {
- processPair(token, sourceFile.getLineAndCharacterOfPosition(token.pos).line, node, previousRange, previousRangeStartLine, previousParent, contextNode, nodeDynamicIndentation);
- }
- }
- function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem, isFirstListItem) {
- var childStartPos = child.getStart(sourceFile);
- var childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line;
- var undecoratedChildStartLine = childStartLine;
- if (child.decorators) {
- undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line;
- }
- // if child is a list item - try to get its indentation, only if parent is within the original range.
- var childIndentationAmount = -1 /* Unknown */;
- if (isListItem && ts.rangeContainsRange(originalRange, parent)) {
- childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation);
- if (childIndentationAmount !== -1 /* Unknown */) {
- inheritedIndentation = childIndentationAmount;
- }
- }
- // child node is outside the target range - do not dive inside
- if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
- if (child.end < originalRange.pos) {
- formattingScanner.skipToEndOf(child);
- }
- return inheritedIndentation;
- }
- if (child.getFullWidth() === 0) {
- return inheritedIndentation;
- }
- while (formattingScanner.isOnToken()) {
- // proceed any parent tokens that are located prior to child.getStart()
- var tokenInfo = formattingScanner.readTokenInfo(node);
- if (tokenInfo.token.end > childStartPos) {
- // stop when formatting scanner advances past the beginning of the child
- break;
- }
- consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, node);
- }
- if (!formattingScanner.isOnToken()) {
- return inheritedIndentation;
- }
- // JSX text shouldn't affect indenting
- if (ts.isToken(child) && child.kind !== 11 /* JsxText */) {
- // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
- var tokenInfo = formattingScanner.readTokenInfo(child);
- ts.Debug.assert(tokenInfo.token.end === child.end, "Token end is child end");
- consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child);
- return inheritedIndentation;
- }
- var effectiveParentStartLine = child.kind === 157 /* Decorator */ ? childStartLine : undecoratedParentStartLine;
- var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine);
- processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta);
- if (child.kind === 11 /* JsxText */) {
- var range = { pos: child.getStart(), end: child.getEnd() };
- if (range.pos !== range.end) { // don't indent zero-width jsx text
- var siblings = parent.getChildren(sourceFile);
- var currentIndex = ts.findIndex(siblings, function (arg) { return arg.pos === child.pos; });
- var previousNode = siblings[currentIndex - 1];
- if (previousNode) {
- // The jsx text needs no indentation whatsoever if it ends on the same line the previous sibling ends on
- if (sourceFile.getLineAndCharacterOfPosition(range.end).line !== sourceFile.getLineAndCharacterOfPosition(previousNode.end).line) {
- // The first line is (already) "indented" if the text starts on the same line as the previous sibling element ends on
- var firstLineIsIndented = sourceFile.getLineAndCharacterOfPosition(range.pos).line === sourceFile.getLineAndCharacterOfPosition(previousNode.end).line;
- indentMultilineCommentOrJsxText(range, childIndentation.indentation, firstLineIsIndented, /*indentFinalLine*/ false, /*jsxStyle*/ true);
- }
- }
- }
- }
- childContextNode = node;
- if (isFirstListItem && parent.kind === 192 /* ArrayLiteralExpression */ && inheritedIndentation === -1 /* Unknown */) {
- inheritedIndentation = childIndentation.indentation;
- }
- return inheritedIndentation;
- }
- function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) {
- ts.Debug.assert(ts.isNodeArray(nodes));
- var listStartToken = getOpenTokenForList(parent, nodes);
- var listDynamicIndentation = parentDynamicIndentation;
- var startLine = parentStartLine;
- if (listStartToken !== 0 /* Unknown */) {
- // introduce a new indentation scope for lists (including list start and end tokens)
- while (formattingScanner.isOnToken()) {
- var tokenInfo = formattingScanner.readTokenInfo(parent);
- if (tokenInfo.token.end > nodes.pos) {
- // stop when formatting scanner moves past the beginning of node list
- break;
- }
- else if (tokenInfo.token.kind === listStartToken) {
- // consume list start token
- startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line;
- consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation, parent);
- var indentationOnListStartToken = void 0;
- if (indentationOnLastIndentedLine !== -1 /* Unknown */) {
- // scanner just processed list start token so consider last indentation as list indentation
- // function foo(): { // last indentation was 0, list item will be indented based on this value
- // foo: number;
- // }: {};
- indentationOnListStartToken = indentationOnLastIndentedLine;
- }
- else {
- var startLinePosition = ts.getLineStartPositionForPosition(tokenInfo.token.pos, sourceFile);
- indentationOnListStartToken = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, tokenInfo.token.pos, sourceFile, options);
- }
- listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentationOnListStartToken, options.indentSize); // TODO: GH#18217
- }
- else {
- // consume any tokens that precede the list as child elements of 'node' using its indentation scope
- consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation, parent);
- }
- }
- }
- var inheritedIndentation = -1 /* Unknown */;
- for (var i = 0; i < nodes.length; i++) {
- var child = nodes[i];
- inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0);
- }
- var listEndToken = getCloseTokenForOpenToken(listStartToken);
- if (listEndToken !== 0 /* Unknown */ && formattingScanner.isOnToken()) {
- var tokenInfo = formattingScanner.readTokenInfo(parent);
- if (tokenInfo.token.kind === 27 /* CommaToken */ && ts.isCallLikeExpression(parent)) {
- var commaTokenLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line;
- if (startLine !== commaTokenLine) {
- formattingScanner.advance();
- tokenInfo = formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(parent) : undefined;
- }
- }
- // consume the list end token only if it is still belong to the parent
- // there might be the case when current token matches end token but does not considered as one
- // function (x: function) <--
- // without this check close paren will be interpreted as list end token for function expression which is wrong
- if (tokenInfo && tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) {
- // consume list end token
- consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent, /*isListEndToken*/ true);
- }
- }
- }
- function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation, container, isListEndToken) {
- ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token));
- var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
- var indentToken = false;
- if (currentTokenInfo.leadingTrivia) {
- processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation);
- }
- var lineAction = 0 /* None */;
- var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token);
- var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
- if (isTokenInRange) {
- var rangeHasError = rangeContainsError(currentTokenInfo.token);
- // save previousRange since processRange will overwrite this value with current one
- var savePreviousRange = previousRange;
- lineAction = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation);
- // do not indent comments\token if token range overlaps with some error
- if (!rangeHasError) {
- if (lineAction === 0 /* None */) {
- // indent token only if end line of previous range does not match start line of the token
- var prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line;
- indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine;
- }
- else {
- indentToken = lineAction === 1 /* LineAdded */;
- }
- }
- }
- if (currentTokenInfo.trailingTrivia) {
- processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation);
- }
- if (indentToken) {
- var tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ?
- dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container, !!isListEndToken) :
- -1 /* Unknown */;
- var indentNextTokenOrTrivia = true;
- if (currentTokenInfo.leadingTrivia) {
- var commentIndentation_1 = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container);
- indentNextTokenOrTrivia = indentTriviaItems(currentTokenInfo.leadingTrivia, commentIndentation_1, indentNextTokenOrTrivia, function (item) { return insertIndentation(item.pos, commentIndentation_1, /*lineAdded*/ false); });
- }
- // indent token only if is it is in target range and does not overlap with any error ranges
- if (tokenIndentation !== -1 /* Unknown */ && indentNextTokenOrTrivia) {
- insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAction === 1 /* LineAdded */);
- lastIndentedLine = tokenStart.line;
- indentationOnLastIndentedLine = tokenIndentation;
- }
- }
- formattingScanner.advance();
- childContextNode = parent;
- }
- }
- function indentTriviaItems(trivia, commentIndentation, indentNextTokenOrTrivia, indentSingleLine) {
- for (var _i = 0, trivia_1 = trivia; _i < trivia_1.length; _i++) {
- var triviaItem = trivia_1[_i];
- var triviaInRange = ts.rangeContainsRange(originalRange, triviaItem);
- switch (triviaItem.kind) {
- case 3 /* MultiLineCommentTrivia */:
- if (triviaInRange) {
- indentMultilineCommentOrJsxText(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia);
- }
- indentNextTokenOrTrivia = false;
- break;
- case 2 /* SingleLineCommentTrivia */:
- if (indentNextTokenOrTrivia && triviaInRange) {
- indentSingleLine(triviaItem);
- }
- indentNextTokenOrTrivia = false;
- break;
- case 4 /* NewLineTrivia */:
- indentNextTokenOrTrivia = true;
- break;
- }
- }
- return indentNextTokenOrTrivia;
- }
- function processTrivia(trivia, parent, contextNode, dynamicIndentation) {
- for (var _i = 0, trivia_2 = trivia; _i < trivia_2.length; _i++) {
- var triviaItem = trivia_2[_i];
- if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) {
- var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos);
- processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation);
- }
- }
- }
- function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) {
- var rangeHasError = rangeContainsError(range);
- var lineAction = 0 /* None */;
- if (!rangeHasError) {
- if (!previousRange) {
- // trim whitespaces starting from the beginning of the span up to the current line
- var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos);
- trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
- }
- else {
- lineAction =
- processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation);
- }
- }
- previousRange = range;
- previousParent = parent;
- previousRangeStartLine = rangeStart.line;
- return lineAction;
- }
- function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) {
- formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode);
- var rules = getRules(formattingContext);
- var trimTrailingWhitespaces = formattingContext.options.trimTrailingWhitespace !== false;
- var lineAction = 0 /* None */;
- if (rules) {
- // Apply rules in reverse order so that higher priority rules (which are first in the array)
- // win in a conflict with lower priority rules.
- ts.forEachRight(rules, function (rule) {
- lineAction = applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
- switch (lineAction) {
- case 2 /* LineRemoved */:
- // Handle the case where the next line is moved to be the end of this line.
- // In this case we don't indent the next line in the next pass.
- if (currentParent.getStart(sourceFile) === currentItem.pos) {
- dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false, contextNode);
- }
- break;
- case 1 /* LineAdded */:
- // Handle the case where token2 is moved to the new line.
- // In this case we indent token2 in the next pass but we set
- // sameLineIndent flag to notify the indenter that the indentation is within the line.
- if (currentParent.getStart(sourceFile) === currentItem.pos) {
- dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true, contextNode);
- }
- break;
- default:
- ts.Debug.assert(lineAction === 0 /* None */);
- }
- // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
- trimTrailingWhitespaces = trimTrailingWhitespaces && !(rule.action & 16 /* DeleteSpace */) && rule.flags !== 1 /* CanDeleteNewLines */;
- });
- }
- else {
- trimTrailingWhitespaces = trimTrailingWhitespaces && currentItem.kind !== 1 /* EndOfFileToken */;
- }
- if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) {
- // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
- trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem);
- }
- return lineAction;
- }
- function insertIndentation(pos, indentation, lineAdded) {
- var indentationString = getIndentationString(indentation, options);
- if (lineAdded) {
- // new line is added before the token by the formatting rules
- // insert indentation string at the very beginning of the token
- recordReplace(pos, 0, indentationString);
- }
- else {
- var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos);
- var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile);
- if (indentation !== characterToColumn(startLinePosition, tokenStart.character) || indentationIsDifferent(indentationString, startLinePosition)) {
- recordReplace(startLinePosition, tokenStart.character, indentationString);
- }
- }
- }
- function characterToColumn(startLinePosition, characterInLine) {
- var column = 0;
- for (var i = 0; i < characterInLine; i++) {
- if (sourceFile.text.charCodeAt(startLinePosition + i) === 9 /* tab */) {
- column += options.tabSize - column % options.tabSize;
- }
- else {
- column++;
- }
- }
- return column;
- }
- function indentationIsDifferent(indentationString, startLinePosition) {
- return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length);
- }
- function indentMultilineCommentOrJsxText(commentRange, indentation, firstLineIsIndented, indentFinalLine, jsxTextStyleIndent) {
- if (indentFinalLine === void 0) { indentFinalLine = true; }
- // split comment in lines
- var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
- var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
- if (startLine === endLine) {
- if (!firstLineIsIndented) {
- // treat as single line comment
- insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false);
- }
- return;
- }
- var parts = [];
- var startPos = commentRange.pos;
- for (var line = startLine; line < endLine; line++) {
- var endOfLine = ts.getEndLinePosition(line, sourceFile);
- parts.push({ pos: startPos, end: endOfLine });
- startPos = ts.getStartPositionOfLine(line + 1, sourceFile);
- }
- if (indentFinalLine) {
- parts.push({ pos: startPos, end: commentRange.end });
- }
- if (parts.length === 0)
- return;
- var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile);
- var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options);
- if (indentation === nonWhitespaceColumnInFirstPart.column && !jsxTextStyleIndent) {
- return;
- }
- var startIndex = 0;
- if (firstLineIsIndented) {
- startIndex = 1;
- startLine++;
- }
- // shift all parts on the delta size
- var delta = indentation - nonWhitespaceColumnInFirstPart.column;
- for (var i = startIndex; i < parts.length; i++, startLine++) {
- var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile);
- var nonWhitespaceCharacterAndColumn = i === 0
- ? nonWhitespaceColumnInFirstPart
- : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options);
- if (jsxTextStyleIndent) {
- // skip adding indentation to blank lines
- if (ts.isLineBreak(sourceFile.text.charCodeAt(ts.getStartPositionOfLine(startLine, sourceFile))))
- continue;
- // reset delta on every line
- delta = indentation - nonWhitespaceCharacterAndColumn.column;
- }
- var newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
- if (newIndentation > 0) {
- var indentationString = getIndentationString(newIndentation, options);
- recordReplace(startLinePos_1, nonWhitespaceCharacterAndColumn.character, indentationString);
- }
- else {
- recordDelete(startLinePos_1, nonWhitespaceCharacterAndColumn.character);
- }
- }
- }
- function trimTrailingWhitespacesForLines(line1, line2, range) {
- for (var line = line1; line < line2; line++) {
- var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile);
- var lineEndPosition = ts.getEndLinePosition(line, sourceFile);
- // do not trim whitespaces in comments or template expression
- if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
- continue;
- }
- var whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition);
- if (whitespaceStart !== -1) {
- ts.Debug.assert(whitespaceStart === lineStartPosition || !ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1)));
- recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart);
- }
- }
- }
- /**
- * @param start The position of the first character in range
- * @param end The position of the last character in range
- */
- function getTrailingWhitespaceStartPosition(start, end) {
- var pos = end;
- while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) {
- pos--;
- }
- if (pos !== end) {
- return pos + 1;
- }
- return -1;
- }
- /**
- * Trimming will be done for lines after the previous range
- */
- function trimTrailingWhitespacesForRemainingRange() {
- var startPosition = previousRange ? previousRange.end : originalRange.pos;
- var startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line;
- var endLine = sourceFile.getLineAndCharacterOfPosition(originalRange.end).line;
- trimTrailingWhitespacesForLines(startLine, endLine + 1, previousRange);
- }
- function recordDelete(start, len) {
- if (len) {
- edits.push(ts.createTextChangeFromStartLength(start, len, ""));
- }
- }
- function recordReplace(start, len, newText) {
- if (len || newText) {
- edits.push(ts.createTextChangeFromStartLength(start, len, newText));
- }
- }
- function recordInsert(start, text) {
- if (text) {
- edits.push(ts.createTextChangeFromStartLength(start, 0, text));
- }
- }
- function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) {
- var onLaterLine = currentStartLine !== previousStartLine;
- switch (rule.action) {
- case 1 /* StopProcessingSpaceActions */:
- // no action required
- return 0 /* None */;
- case 16 /* DeleteSpace */:
- if (previousRange.end !== currentRange.pos) {
- // delete characters starting from t1.end up to t2.pos exclusive
- recordDelete(previousRange.end, currentRange.pos - previousRange.end);
- return onLaterLine ? 2 /* LineRemoved */ : 0 /* None */;
- }
- break;
- case 32 /* DeleteToken */:
- recordDelete(previousRange.pos, previousRange.end - previousRange.pos);
- break;
- case 8 /* InsertNewLine */:
- // exit early if we on different lines and rule cannot change number of newlines
- // if line1 and line2 are on subsequent lines then no edits are required - ok to exit
- // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines
- if (rule.flags !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) {
- return 0 /* None */;
- }
- // edit should not be applied if we have one line feed between elements
- var lineDelta = currentStartLine - previousStartLine;
- if (lineDelta !== 1) {
- recordReplace(previousRange.end, currentRange.pos - previousRange.end, ts.getNewLineOrDefaultFromHost(host, options));
- return onLaterLine ? 0 /* None */ : 1 /* LineAdded */;
- }
- break;
- case 4 /* InsertSpace */:
- // exit early if we on different lines and rule cannot change number of newlines
- if (rule.flags !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) {
- return 0 /* None */;
- }
- var posDelta = currentRange.pos - previousRange.end;
- if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) {
- recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
- return onLaterLine ? 2 /* LineRemoved */ : 0 /* None */;
- }
- break;
- case 64 /* InsertTrailingSemicolon */:
- recordInsert(previousRange.end, ";");
- }
- return 0 /* None */;
- }
- }
- var LineAction;
- (function (LineAction) {
- LineAction[LineAction["None"] = 0] = "None";
- LineAction[LineAction["LineAdded"] = 1] = "LineAdded";
- LineAction[LineAction["LineRemoved"] = 2] = "LineRemoved";
- })(LineAction || (LineAction = {}));
- /**
- * @param precedingToken pass `null` if preceding token was already computed and result was `undefined`.
- */
- function getRangeOfEnclosingComment(sourceFile, position, precedingToken, tokenAtPosition) {
- if (tokenAtPosition === void 0) { tokenAtPosition = ts.getTokenAtPosition(sourceFile, position); }
- var jsdoc = ts.findAncestor(tokenAtPosition, ts.isJSDoc);
- if (jsdoc)
- tokenAtPosition = jsdoc.parent;
- var tokenStart = tokenAtPosition.getStart(sourceFile);
- if (tokenStart <= position && position < tokenAtPosition.getEnd()) {
- return undefined;
- }
- // eslint-disable-next-line no-null/no-null
- precedingToken = precedingToken === null ? undefined : precedingToken === undefined ? ts.findPrecedingToken(position, sourceFile) : precedingToken;
- // Between two consecutive tokens, all comments are either trailing on the former
- // or leading on the latter (and none are in both lists).
- var trailingRangesOfPreviousToken = precedingToken && ts.getTrailingCommentRanges(sourceFile.text, precedingToken.end);
- var leadingCommentRangesOfNextToken = ts.getLeadingCommentRangesOfNode(tokenAtPosition, sourceFile);
- var commentRanges = ts.concatenate(trailingRangesOfPreviousToken, leadingCommentRangesOfNextToken);
- return commentRanges && ts.find(commentRanges, function (range) { return ts.rangeContainsPositionExclusive(range, position) ||
- // The end marker of a single-line comment does not include the newline character.
- // With caret at `^`, in the following case, we are inside a comment (^ denotes the cursor position):
- //
- // // asdf ^\n
- //
- // But for closed multi-line comments, we don't want to be inside the comment in the following case:
- //
- // /* asdf */^
- //
- // However, unterminated multi-line comments *do* contain their end.
- //
- // Internally, we represent the end of the comment at the newline and closing '/', respectively.
- //
- position === range.end && (range.kind === 2 /* SingleLineCommentTrivia */ || position === sourceFile.getFullWidth()); });
- }
- formatting.getRangeOfEnclosingComment = getRangeOfEnclosingComment;
- function getOpenTokenForList(node, list) {
- switch (node.kind) {
- case 162 /* Constructor */:
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 161 /* MethodDeclaration */:
- case 160 /* MethodSignature */:
- case 202 /* ArrowFunction */:
- if (node.typeParameters === list) {
- return 29 /* LessThanToken */;
- }
- else if (node.parameters === list) {
- return 20 /* OpenParenToken */;
- }
- break;
- case 196 /* CallExpression */:
- case 197 /* NewExpression */:
- if (node.typeArguments === list) {
- return 29 /* LessThanToken */;
- }
- else if (node.arguments === list) {
- return 20 /* OpenParenToken */;
- }
- break;
- case 169 /* TypeReference */:
- if (node.typeArguments === list) {
- return 29 /* LessThanToken */;
- }
- break;
- case 173 /* TypeLiteral */:
- return 18 /* OpenBraceToken */;
- }
- return 0 /* Unknown */;
- }
- function getCloseTokenForOpenToken(kind) {
- switch (kind) {
- case 20 /* OpenParenToken */:
- return 21 /* CloseParenToken */;
- case 29 /* LessThanToken */:
- return 31 /* GreaterThanToken */;
- case 18 /* OpenBraceToken */:
- return 19 /* CloseBraceToken */;
- }
- return 0 /* Unknown */;
- }
- var internedSizes;
- var internedTabsIndentation;
- var internedSpacesIndentation;
- function getIndentationString(indentation, options) {
- // reset interned strings if FormatCodeOptions were changed
- var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize);
- if (resetInternedStrings) {
- internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize };
- internedTabsIndentation = internedSpacesIndentation = undefined;
- }
- if (!options.convertTabsToSpaces) {
- var tabs = Math.floor(indentation / options.tabSize);
- var spaces = indentation - tabs * options.tabSize;
- var tabString = void 0;
- if (!internedTabsIndentation) {
- internedTabsIndentation = [];
- }
- if (internedTabsIndentation[tabs] === undefined) {
- internedTabsIndentation[tabs] = tabString = ts.repeatString("\t", tabs);
- }
- else {
- tabString = internedTabsIndentation[tabs];
- }
- return spaces ? tabString + ts.repeatString(" ", spaces) : tabString;
- }
- else {
- var spacesString = void 0;
- var quotient = Math.floor(indentation / options.indentSize);
- var remainder = indentation % options.indentSize;
- if (!internedSpacesIndentation) {
- internedSpacesIndentation = [];
- }
- if (internedSpacesIndentation[quotient] === undefined) {
- spacesString = ts.repeatString(" ", options.indentSize * quotient);
- internedSpacesIndentation[quotient] = spacesString;
- }
- else {
- spacesString = internedSpacesIndentation[quotient];
- }
- return remainder ? spacesString + ts.repeatString(" ", remainder) : spacesString;
- }
- }
- formatting.getIndentationString = getIndentationString;
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- var SmartIndenter;
- (function (SmartIndenter) {
- var Value;
- (function (Value) {
- Value[Value["Unknown"] = -1] = "Unknown";
- })(Value || (Value = {}));
- /**
- * @param assumeNewLineBeforeCloseBrace
- * `false` when called on text from a real source file.
- * `true` when we need to assume `position` is on a newline.
- *
- * This is useful for codefixes. Consider
- * ```
- * function f() {
- * |}
- * ```
- * with `position` at `|`.
- *
- * When inserting some text after an open brace, we would like to get indentation as if a newline was already there.
- * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior.
- */
- function getIndentation(position, sourceFile, options, assumeNewLineBeforeCloseBrace) {
- if (assumeNewLineBeforeCloseBrace === void 0) { assumeNewLineBeforeCloseBrace = false; }
- if (position > sourceFile.text.length) {
- return getBaseIndentation(options); // past EOF
- }
- // no indentation when the indent style is set to none,
- // so we can return fast
- if (options.indentStyle === ts.IndentStyle.None) {
- return 0;
- }
- var precedingToken = ts.findPrecedingToken(position, sourceFile, /*startNode*/ undefined, /*excludeJsdoc*/ true);
- // eslint-disable-next-line no-null/no-null
- var enclosingCommentRange = formatting.getRangeOfEnclosingComment(sourceFile, position, precedingToken || null);
- if (enclosingCommentRange && enclosingCommentRange.kind === 3 /* MultiLineCommentTrivia */) {
- return getCommentIndent(sourceFile, position, options, enclosingCommentRange);
- }
- if (!precedingToken) {
- return getBaseIndentation(options);
- }
- // no indentation in string \regex\template literals
- var precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind);
- if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && position < precedingToken.end) {
- return 0;
- }
- var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
- // indentation is first non-whitespace character in a previous line
- // for block indentation, we should look for a line which contains something that's not
- // whitespace.
- if (options.indentStyle === ts.IndentStyle.Block) {
- return getBlockIndent(sourceFile, position, options);
- }
- if (precedingToken.kind === 27 /* CommaToken */ && precedingToken.parent.kind !== 209 /* BinaryExpression */) {
- // previous token is comma that separates items in list - find the previous item and try to derive indentation from it
- var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation;
- }
- }
- var containerList = getListByPosition(position, precedingToken.parent, sourceFile);
- // use list position if the preceding token is before any list items
- if (containerList && !ts.rangeContainsRange(containerList, precedingToken)) {
- return getActualIndentationForListStartLine(containerList, sourceFile, options) + options.indentSize; // TODO: GH#18217
- }
- return getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options);
- }
- SmartIndenter.getIndentation = getIndentation;
- function getCommentIndent(sourceFile, position, options, enclosingCommentRange) {
- var previousLine = ts.getLineAndCharacterOfPosition(sourceFile, position).line - 1;
- var commentStartLine = ts.getLineAndCharacterOfPosition(sourceFile, enclosingCommentRange.pos).line;
- ts.Debug.assert(commentStartLine >= 0);
- if (previousLine <= commentStartLine) {
- return findFirstNonWhitespaceColumn(ts.getStartPositionOfLine(commentStartLine, sourceFile), position, sourceFile, options);
- }
- var startPositionOfLine = ts.getStartPositionOfLine(previousLine, sourceFile);
- var _a = findFirstNonWhitespaceCharacterAndColumn(startPositionOfLine, position, sourceFile, options), column = _a.column, character = _a.character;
- if (column === 0) {
- return column;
- }
- var firstNonWhitespaceCharacterCode = sourceFile.text.charCodeAt(startPositionOfLine + character);
- return firstNonWhitespaceCharacterCode === 42 /* asterisk */ ? column - 1 : column;
- }
- function getBlockIndent(sourceFile, position, options) {
- // move backwards until we find a line with a non-whitespace character,
- // then find the first non-whitespace character for that line.
- var current = position;
- while (current > 0) {
- var char = sourceFile.text.charCodeAt(current);
- if (!ts.isWhiteSpaceLike(char)) {
- break;
- }
- current--;
- }
- var lineStart = ts.getLineStartPositionForPosition(current, sourceFile);
- return findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options);
- }
- function getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options) {
- // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken'
- // if such node is found - compute initial indentation for 'position' inside this node
- var previous;
- var current = precedingToken;
- while (current) {
- if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) {
- var currentStart = getStartLineAndCharacterForNode(current, sourceFile);
- var nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile);
- var indentationDelta = nextTokenKind !== 0 /* Unknown */
- // handle cases when codefix is about to be inserted before the close brace
- ? assumeNewLineBeforeCloseBrace && nextTokenKind === 2 /* CloseBrace */ ? options.indentSize : 0
- : lineAtPosition !== currentStart.line ? options.indentSize : 0;
- return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, /*isNextChild*/ true, options); // TODO: GH#18217
- }
- // check if current node is a list item - if yes, take indentation from it
- // do not consider parent-child line sharing yet:
- // function foo(a
- // | preceding node 'a' does share line with its parent but indentation is expected
- var actualIndentation = getActualIndentationForListItem(current, sourceFile, options, /*listIndentsChild*/ true);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation;
- }
- previous = current;
- current = current.parent;
- }
- // no parent was found - return the base indentation of the SourceFile
- return getBaseIndentation(options);
- }
- function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) {
- var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
- return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, /*isNextChild*/ false, options);
- }
- SmartIndenter.getIndentationForNode = getIndentationForNode;
- function getBaseIndentation(options) {
- return options.baseIndentSize || 0;
- }
- SmartIndenter.getBaseIndentation = getBaseIndentation;
- function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, isNextChild, options) {
- var parent = current.parent;
- // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if
- // * parent and child nodes start on the same line, or
- // * parent is an IfStatement and child starts on the same line as an 'else clause'.
- while (parent) {
- var useActualIndentation = true;
- if (ignoreActualIndentationRange) {
- var start = current.getStart(sourceFile);
- useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end;
- }
- var containingListOrParentStart = getContainingListOrParentStart(parent, current, sourceFile);
- var parentAndChildShareLine = containingListOrParentStart.line === currentStart.line ||
- childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile);
- if (useActualIndentation) {
- // check if current node is a list item - if yes, take indentation from it
- var actualIndentation = getActualIndentationForListItem(current, sourceFile, options, !parentAndChildShareLine);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation + indentationDelta;
- }
- // try to fetch actual indentation for current node from source text
- actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation + indentationDelta;
- }
- }
- // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
- if (shouldIndentChildNode(options, parent, current, sourceFile, isNextChild) && !parentAndChildShareLine) {
- indentationDelta += options.indentSize;
- }
- // In our AST, a call argument's `parent` is the call-expression, not the argument list.
- // We would like to increase indentation based on the relationship between an argument and its argument-list,
- // so we spoof the starting position of the (parent) call-expression to match the (non-parent) argument-list.
- // But, the spoofed start-value could then cause a problem when comparing the start position of the call-expression
- // to *its* parent (in the case of an iife, an expression statement), adding an extra level of indentation.
- //
- // Instead, when at an argument, we unspoof the starting position of the enclosing call expression
- // *after* applying indentation for the argument.
- var useTrueStart = isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile);
- current = parent;
- parent = current.parent;
- currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart(sourceFile)) : containingListOrParentStart;
- }
- return indentationDelta + getBaseIndentation(options);
- }
- function getContainingListOrParentStart(parent, child, sourceFile) {
- var containingList = getContainingList(child, sourceFile);
- var startPos = containingList ? containingList.pos : parent.getStart(sourceFile);
- return sourceFile.getLineAndCharacterOfPosition(startPos);
- }
- /*
- * Function returns Value.Unknown if indentation cannot be determined
- */
- function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) {
- // previous token is comma that separates items in list - find the previous item and try to derive indentation from it
- var commaItemInfo = ts.findListItemInfo(commaToken);
- if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
- return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
- }
- else {
- // handle broken code gracefully
- return -1 /* Unknown */;
- }
- }
- /*
- * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression)
- */
- function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) {
- // actual indentation is used for statements\declarations if one of cases below is true:
- // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually
- // - parent and child are not on the same line
- var useActualIndentation = (ts.isDeclaration(current) || ts.isStatementButNotDeclaration(current)) &&
- (parent.kind === 290 /* SourceFile */ || !parentAndChildShareLine);
- if (!useActualIndentation) {
- return -1 /* Unknown */;
- }
- return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
- }
- var NextTokenKind;
- (function (NextTokenKind) {
- NextTokenKind[NextTokenKind["Unknown"] = 0] = "Unknown";
- NextTokenKind[NextTokenKind["OpenBrace"] = 1] = "OpenBrace";
- NextTokenKind[NextTokenKind["CloseBrace"] = 2] = "CloseBrace";
- })(NextTokenKind || (NextTokenKind = {}));
- function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) {
- var nextToken = ts.findNextToken(precedingToken, current, sourceFile);
- if (!nextToken) {
- return 0 /* Unknown */;
- }
- if (nextToken.kind === 18 /* OpenBraceToken */) {
- // open braces are always indented at the parent level
- return 1 /* OpenBrace */;
- }
- else if (nextToken.kind === 19 /* CloseBraceToken */) {
- // close braces are indented at the parent level if they are located on the same line with cursor
- // this means that if new line will be added at $ position, this case will be indented
- // class A {
- // $
- // }
- /// and this one - not
- // class A {
- // $}
- var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
- return lineAtPosition === nextTokenStartLine ? 2 /* CloseBrace */ : 0 /* Unknown */;
- }
- return 0 /* Unknown */;
- }
- function getStartLineAndCharacterForNode(n, sourceFile) {
- return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
- }
- function isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, child, childStartLine, sourceFile) {
- if (!(ts.isCallExpression(parent) && ts.contains(parent.arguments, child))) {
- return false;
- }
- var expressionOfCallExpressionEnd = parent.expression.getEnd();
- var expressionOfCallExpressionEndLine = ts.getLineAndCharacterOfPosition(sourceFile, expressionOfCallExpressionEnd).line;
- return expressionOfCallExpressionEndLine === childStartLine;
- }
- SmartIndenter.isArgumentAndStartLineOverlapsExpressionBeingCalled = isArgumentAndStartLineOverlapsExpressionBeingCalled;
- function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) {
- if (parent.kind === 227 /* IfStatement */ && parent.elseStatement === child) {
- var elseKeyword = ts.findChildOfKind(parent, 87 /* ElseKeyword */, sourceFile);
- ts.Debug.assert(elseKeyword !== undefined);
- var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
- return elseKeywordStartLine === childStartLine;
- }
- return false;
- }
- SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement;
- function argumentStartsOnSameLineAsPreviousArgument(parent, child, childStartLine, sourceFile) {
- if (ts.isCallOrNewExpression(parent)) {
- if (!parent.arguments)
- return false;
- var currentNode = ts.find(parent.arguments, function (arg) { return arg.pos === child.pos; });
- // If it's not one of the arguments, don't look past this
- if (!currentNode)
- return false;
- var currentIndex = parent.arguments.indexOf(currentNode);
- if (currentIndex === 0)
- return false; // Can't look at previous node if first
- var previousNode = parent.arguments[currentIndex - 1];
- var lineOfPreviousNode = ts.getLineAndCharacterOfPosition(sourceFile, previousNode.getEnd()).line;
- if (childStartLine === lineOfPreviousNode) {
- return true;
- }
- }
- return false;
- }
- SmartIndenter.argumentStartsOnSameLineAsPreviousArgument = argumentStartsOnSameLineAsPreviousArgument;
- function getContainingList(node, sourceFile) {
- return node.parent && getListByRange(node.getStart(sourceFile), node.getEnd(), node.parent, sourceFile);
- }
- SmartIndenter.getContainingList = getContainingList;
- function getListByPosition(pos, node, sourceFile) {
- return node && getListByRange(pos, pos, node, sourceFile);
- }
- function getListByRange(start, end, node, sourceFile) {
- switch (node.kind) {
- case 169 /* TypeReference */:
- return getList(node.typeArguments);
- case 193 /* ObjectLiteralExpression */:
- return getList(node.properties);
- case 192 /* ArrayLiteralExpression */:
- return getList(node.elements);
- case 173 /* TypeLiteral */:
- return getList(node.members);
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 202 /* ArrowFunction */:
- case 161 /* MethodDeclaration */:
- case 160 /* MethodSignature */:
- case 165 /* CallSignature */:
- case 162 /* Constructor */:
- case 171 /* ConstructorType */:
- case 166 /* ConstructSignature */:
- return getList(node.typeParameters) || getList(node.parameters);
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 246 /* InterfaceDeclaration */:
- case 247 /* TypeAliasDeclaration */:
- case 321 /* JSDocTemplateTag */:
- return getList(node.typeParameters);
- case 197 /* NewExpression */:
- case 196 /* CallExpression */:
- return getList(node.typeArguments) || getList(node.arguments);
- case 243 /* VariableDeclarationList */:
- return getList(node.declarations);
- case 257 /* NamedImports */:
- case 261 /* NamedExports */:
- return getList(node.elements);
- case 189 /* ObjectBindingPattern */:
- case 190 /* ArrayBindingPattern */:
- return getList(node.elements);
- }
- function getList(list) {
- return list && ts.rangeContainsStartEnd(getVisualListRange(node, list, sourceFile), start, end) ? list : undefined;
- }
- }
- function getVisualListRange(node, list, sourceFile) {
- var children = node.getChildren(sourceFile);
- for (var i = 1; i < children.length - 1; i++) {
- if (children[i].pos === list.pos && children[i].end === list.end) {
- return { pos: children[i - 1].end, end: children[i + 1].getStart(sourceFile) };
- }
- }
- return list;
- }
- function getActualIndentationForListStartLine(list, sourceFile, options) {
- if (!list) {
- return -1 /* Unknown */;
- }
- return findColumnForFirstNonWhitespaceCharacterInLine(sourceFile.getLineAndCharacterOfPosition(list.pos), sourceFile, options);
- }
- function getActualIndentationForListItem(node, sourceFile, options, listIndentsChild) {
- if (node.parent && node.parent.kind === 243 /* VariableDeclarationList */) {
- // VariableDeclarationList has no wrapping tokens
- return -1 /* Unknown */;
- }
- var containingList = getContainingList(node, sourceFile);
- if (containingList) {
- var index = containingList.indexOf(node);
- if (index !== -1) {
- var result = deriveActualIndentationFromList(containingList, index, sourceFile, options);
- if (result !== -1 /* Unknown */) {
- return result;
- }
- }
- return getActualIndentationForListStartLine(containingList, sourceFile, options) + (listIndentsChild ? options.indentSize : 0); // TODO: GH#18217
- }
- return -1 /* Unknown */;
- }
- function deriveActualIndentationFromList(list, index, sourceFile, options) {
- ts.Debug.assert(index >= 0 && index < list.length);
- var node = list[index];
- // walk toward the start of the list starting from current node and check if the line is the same for all items.
- // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i]
- var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile);
- for (var i = index - 1; i >= 0; i--) {
- if (list[i].kind === 27 /* CommaToken */) {
- continue;
- }
- // skip list items that ends on the same line with the current list element
- var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line;
- if (prevEndLine !== lineAndCharacter.line) {
- return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options);
- }
- lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile);
- }
- return -1 /* Unknown */;
- }
- function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) {
- var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
- return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
- }
- /**
- * Character is the actual index of the character since the beginning of the line.
- * Column - position of the character after expanding tabs to spaces.
- * "0\t2$"
- * value of 'character' for '$' is 3
- * value of 'column' for '$' is 6 (assuming that tab size is 4)
- */
- function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) {
- var character = 0;
- var column = 0;
- for (var pos = startPos; pos < endPos; pos++) {
- var ch = sourceFile.text.charCodeAt(pos);
- if (!ts.isWhiteSpaceSingleLine(ch)) {
- break;
- }
- if (ch === 9 /* tab */) {
- column += options.tabSize + (column % options.tabSize);
- }
- else {
- column++;
- }
- character++;
- }
- return { column: column, character: character };
- }
- SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn;
- function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) {
- return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
- }
- SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn;
- function nodeWillIndentChild(settings, parent, child, sourceFile, indentByDefault) {
- var childKind = child ? child.kind : 0 /* Unknown */;
- switch (parent.kind) {
- case 226 /* ExpressionStatement */:
- case 245 /* ClassDeclaration */:
- case 214 /* ClassExpression */:
- case 246 /* InterfaceDeclaration */:
- case 248 /* EnumDeclaration */:
- case 247 /* TypeAliasDeclaration */:
- case 192 /* ArrayLiteralExpression */:
- case 223 /* Block */:
- case 250 /* ModuleBlock */:
- case 193 /* ObjectLiteralExpression */:
- case 173 /* TypeLiteral */:
- case 186 /* MappedType */:
- case 175 /* TupleType */:
- case 251 /* CaseBlock */:
- case 278 /* DefaultClause */:
- case 277 /* CaseClause */:
- case 200 /* ParenthesizedExpression */:
- case 194 /* PropertyAccessExpression */:
- case 196 /* CallExpression */:
- case 197 /* NewExpression */:
- case 225 /* VariableStatement */:
- case 259 /* ExportAssignment */:
- case 235 /* ReturnStatement */:
- case 210 /* ConditionalExpression */:
- case 190 /* ArrayBindingPattern */:
- case 189 /* ObjectBindingPattern */:
- case 268 /* JsxOpeningElement */:
- case 271 /* JsxOpeningFragment */:
- case 267 /* JsxSelfClosingElement */:
- case 276 /* JsxExpression */:
- case 160 /* MethodSignature */:
- case 165 /* CallSignature */:
- case 166 /* ConstructSignature */:
- case 156 /* Parameter */:
- case 170 /* FunctionType */:
- case 171 /* ConstructorType */:
- case 182 /* ParenthesizedType */:
- case 198 /* TaggedTemplateExpression */:
- case 206 /* AwaitExpression */:
- case 261 /* NamedExports */:
- case 257 /* NamedImports */:
- case 263 /* ExportSpecifier */:
- case 258 /* ImportSpecifier */:
- case 159 /* PropertyDeclaration */:
- return true;
- case 242 /* VariableDeclaration */:
- case 281 /* PropertyAssignment */:
- case 209 /* BinaryExpression */:
- if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === 193 /* ObjectLiteralExpression */) { // TODO: GH#18217
- return rangeIsOnOneLine(sourceFile, child);
- }
- if (parent.kind !== 209 /* BinaryExpression */) {
- return true;
- }
- break;
- case 228 /* DoStatement */:
- case 229 /* WhileStatement */:
- case 231 /* ForInStatement */:
- case 232 /* ForOfStatement */:
- case 230 /* ForStatement */:
- case 227 /* IfStatement */:
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- case 161 /* MethodDeclaration */:
- case 202 /* ArrowFunction */:
- case 162 /* Constructor */:
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- return childKind !== 223 /* Block */;
- case 260 /* ExportDeclaration */:
- return childKind !== 261 /* NamedExports */;
- case 254 /* ImportDeclaration */:
- return childKind !== 255 /* ImportClause */ ||
- (!!child.namedBindings && child.namedBindings.kind !== 257 /* NamedImports */);
- case 266 /* JsxElement */:
- return childKind !== 269 /* JsxClosingElement */;
- case 270 /* JsxFragment */:
- return childKind !== 272 /* JsxClosingFragment */;
- case 179 /* IntersectionType */:
- case 178 /* UnionType */:
- if (childKind === 173 /* TypeLiteral */) {
- return false;
- }
- // falls through
- }
- // No explicit rule for given nodes so the result will follow the default value argument
- return indentByDefault;
- }
- SmartIndenter.nodeWillIndentChild = nodeWillIndentChild;
- function isControlFlowEndingStatement(kind, parent) {
- switch (kind) {
- case 235 /* ReturnStatement */:
- case 239 /* ThrowStatement */:
- case 233 /* ContinueStatement */:
- case 234 /* BreakStatement */:
- return parent.kind !== 223 /* Block */;
- default:
- return false;
- }
- }
- /**
- * True when the parent node should indent the given child by an explicit rule.
- * @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child.
- */
- function shouldIndentChildNode(settings, parent, child, sourceFile, isNextChild) {
- if (isNextChild === void 0) { isNextChild = false; }
- return nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false)
- && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent));
- }
- SmartIndenter.shouldIndentChildNode = shouldIndentChildNode;
- function rangeIsOnOneLine(sourceFile, range) {
- var rangeStart = ts.skipTrivia(sourceFile.text, range.pos);
- var startLine = sourceFile.getLineAndCharacterOfPosition(rangeStart).line;
- var endLine = sourceFile.getLineAndCharacterOfPosition(range.end).line;
- return startLine === endLine;
- }
- })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {}));
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var textChanges;
- (function (textChanges_3) {
- /**
- * Currently for simplicity we store recovered positions on the node itself.
- * It can be changed to side-table later if we decide that current design is too invasive.
- */
- function getPos(n) {
- var result = n.__pos;
- ts.Debug.assert(typeof result === "number");
- return result;
- }
- function setPos(n, pos) {
- ts.Debug.assert(typeof pos === "number");
- n.__pos = pos;
- }
- function getEnd(n) {
- var result = n.__end;
- ts.Debug.assert(typeof result === "number");
- return result;
- }
- function setEnd(n, end) {
- ts.Debug.assert(typeof end === "number");
- n.__end = end;
- }
- var LeadingTriviaOption;
- (function (LeadingTriviaOption) {
- /** Exclude all leading trivia (use getStart()) */
- LeadingTriviaOption[LeadingTriviaOption["Exclude"] = 0] = "Exclude";
- /** Include leading trivia and,
- * if there are no line breaks between the node and the previous token,
- * include all trivia between the node and the previous token
- */
- LeadingTriviaOption[LeadingTriviaOption["IncludeAll"] = 1] = "IncludeAll";
- /**
- * Include attached JSDoc comments
- */
- LeadingTriviaOption[LeadingTriviaOption["JSDoc"] = 2] = "JSDoc";
- /**
- * Only delete trivia on the same line as getStart().
- * Used to avoid deleting leading comments
- */
- LeadingTriviaOption[LeadingTriviaOption["StartLine"] = 3] = "StartLine";
- })(LeadingTriviaOption = textChanges_3.LeadingTriviaOption || (textChanges_3.LeadingTriviaOption = {}));
- var TrailingTriviaOption;
- (function (TrailingTriviaOption) {
- /** Exclude all trailing trivia (use getEnd()) */
- TrailingTriviaOption[TrailingTriviaOption["Exclude"] = 0] = "Exclude";
- /** Include trailing trivia */
- TrailingTriviaOption[TrailingTriviaOption["Include"] = 1] = "Include";
- })(TrailingTriviaOption = textChanges_3.TrailingTriviaOption || (textChanges_3.TrailingTriviaOption = {}));
- function skipWhitespacesAndLineBreaks(text, start) {
- return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
- }
- function hasCommentsBeforeLineBreak(text, start) {
- var i = start;
- while (i < text.length) {
- var ch = text.charCodeAt(i);
- if (ts.isWhiteSpaceSingleLine(ch)) {
- i++;
- continue;
- }
- return ch === 47 /* slash */;
- }
- return false;
- }
- var useNonAdjustedPositions = {
- leadingTriviaOption: LeadingTriviaOption.Exclude,
- trailingTriviaOption: TrailingTriviaOption.Exclude,
- };
- var ChangeKind;
- (function (ChangeKind) {
- ChangeKind[ChangeKind["Remove"] = 0] = "Remove";
- ChangeKind[ChangeKind["ReplaceWithSingleNode"] = 1] = "ReplaceWithSingleNode";
- ChangeKind[ChangeKind["ReplaceWithMultipleNodes"] = 2] = "ReplaceWithMultipleNodes";
- ChangeKind[ChangeKind["Text"] = 3] = "Text";
- })(ChangeKind || (ChangeKind = {}));
- function getAdjustedRange(sourceFile, startNode, endNode, options) {
- return { pos: getAdjustedStartPosition(sourceFile, startNode, options), end: getAdjustedEndPosition(sourceFile, endNode, options) };
- }
- function getAdjustedStartPosition(sourceFile, node, options) {
- var leadingTriviaOption = options.leadingTriviaOption;
- if (leadingTriviaOption === LeadingTriviaOption.Exclude) {
- return node.getStart(sourceFile);
- }
- if (leadingTriviaOption === LeadingTriviaOption.StartLine) {
- return ts.getLineStartPositionForPosition(node.getStart(sourceFile), sourceFile);
- }
- if (leadingTriviaOption === LeadingTriviaOption.JSDoc) {
- var JSDocComments = ts.getJSDocCommentRanges(node, sourceFile.text);
- if (JSDocComments === null || JSDocComments === void 0 ? void 0 : JSDocComments.length) {
- return ts.getLineStartPositionForPosition(JSDocComments[0].pos, sourceFile);
- }
- }
- var fullStart = node.getFullStart();
- var start = node.getStart(sourceFile);
- if (fullStart === start) {
- return start;
- }
- var fullStartLine = ts.getLineStartPositionForPosition(fullStart, sourceFile);
- var startLine = ts.getLineStartPositionForPosition(start, sourceFile);
- if (startLine === fullStartLine) {
- // full start and start of the node are on the same line
- // a, b;
- // ^ ^
- // | start
- // fullstart
- // when b is replaced - we usually want to keep the leading trvia
- // when b is deleted - we delete it
- return leadingTriviaOption === LeadingTriviaOption.IncludeAll ? fullStart : start;
- }
- // get start position of the line following the line that contains fullstart position
- // (but only if the fullstart isn't the very beginning of the file)
- var nextLineStart = fullStart > 0 ? 1 : 0;
- var adjustedStartPosition = ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, sourceFile);
- // skip whitespaces/newlines
- adjustedStartPosition = skipWhitespacesAndLineBreaks(sourceFile.text, adjustedStartPosition);
- return ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile);
- }
- function getAdjustedEndPosition(sourceFile, node, options) {
- var end = node.end;
- var trailingTriviaOption = options.trailingTriviaOption;
- if (trailingTriviaOption === TrailingTriviaOption.Exclude || (ts.isExpression(node) && trailingTriviaOption !== TrailingTriviaOption.Include)) {
- return end;
- }
- var newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true);
- return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1)))
- ? newEnd
- : end;
- }
- /**
- * Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element
- */
- function isSeparator(node, candidate) {
- return !!candidate && !!node.parent && (candidate.kind === 27 /* CommaToken */ || (candidate.kind === 26 /* SemicolonToken */ && node.parent.kind === 193 /* ObjectLiteralExpression */));
- }
- function spaces(count) {
- var s = "";
- for (var i = 0; i < count; i++) {
- s += " ";
- }
- return s;
- }
- function isThisTypeAnnotatable(containingFunction) {
- return ts.isFunctionExpression(containingFunction) || ts.isFunctionDeclaration(containingFunction);
- }
- textChanges_3.isThisTypeAnnotatable = isThisTypeAnnotatable;
- var ChangeTracker = /** @class */ (function () {
- /** Public for tests only. Other callers should use `ChangeTracker.with`. */
- function ChangeTracker(newLineCharacter, formatContext) {
- this.newLineCharacter = newLineCharacter;
- this.formatContext = formatContext;
- this.changes = [];
- this.newFiles = [];
- this.classesWithNodesInsertedAtStart = ts.createMap(); // Set implemented as Map
- this.deletedNodes = [];
- }
- ChangeTracker.fromContext = function (context) {
- return new ChangeTracker(ts.getNewLineOrDefaultFromHost(context.host, context.formatContext.options), context.formatContext);
- };
- ChangeTracker.with = function (context, cb) {
- var tracker = ChangeTracker.fromContext(context);
- cb(tracker);
- return tracker.getChanges();
- };
- ChangeTracker.prototype.pushRaw = function (sourceFile, change) {
- ts.Debug.assertEqual(sourceFile.fileName, change.fileName);
- for (var _i = 0, _a = change.textChanges; _i < _a.length; _i++) {
- var c = _a[_i];
- this.changes.push({
- kind: ChangeKind.Text,
- sourceFile: sourceFile,
- text: c.newText,
- range: ts.createTextRangeFromSpan(c.span),
- });
- }
- };
- ChangeTracker.prototype.deleteRange = function (sourceFile, range) {
- this.changes.push({ kind: ChangeKind.Remove, sourceFile: sourceFile, range: range });
- };
- ChangeTracker.prototype.delete = function (sourceFile, node) {
- this.deletedNodes.push({ sourceFile: sourceFile, node: node });
- };
- ChangeTracker.prototype.deleteNode = function (sourceFile, node, options) {
- if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; }
- this.deleteRange(sourceFile, getAdjustedRange(sourceFile, node, node, options));
- };
- ChangeTracker.prototype.deleteModifier = function (sourceFile, modifier) {
- this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: ts.skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) });
- };
- ChangeTracker.prototype.deleteNodeRange = function (sourceFile, startNode, endNode, options) {
- if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; }
- var startPosition = getAdjustedStartPosition(sourceFile, startNode, options);
- var endPosition = getAdjustedEndPosition(sourceFile, endNode, options);
- this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
- };
- ChangeTracker.prototype.deleteNodeRangeExcludingEnd = function (sourceFile, startNode, afterEndNode, options) {
- if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; }
- var startPosition = getAdjustedStartPosition(sourceFile, startNode, options);
- var endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options);
- this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
- };
- ChangeTracker.prototype.replaceRange = function (sourceFile, range, newNode, options) {
- if (options === void 0) { options = {}; }
- this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile: sourceFile, range: range, options: options, node: newNode });
- };
- ChangeTracker.prototype.replaceNode = function (sourceFile, oldNode, newNode, options) {
- if (options === void 0) { options = useNonAdjustedPositions; }
- this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options);
- };
- ChangeTracker.prototype.replaceNodeRange = function (sourceFile, startNode, endNode, newNode, options) {
- if (options === void 0) { options = useNonAdjustedPositions; }
- this.replaceRange(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNode, options);
- };
- ChangeTracker.prototype.replaceRangeWithNodes = function (sourceFile, range, newNodes, options) {
- if (options === void 0) { options = {}; }
- this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile: sourceFile, range: range, options: options, nodes: newNodes });
- };
- ChangeTracker.prototype.replaceNodeWithNodes = function (sourceFile, oldNode, newNodes, options) {
- if (options === void 0) { options = useNonAdjustedPositions; }
- this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options);
- };
- ChangeTracker.prototype.replaceNodeWithText = function (sourceFile, oldNode, text) {
- this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), text);
- };
- ChangeTracker.prototype.replaceNodeRangeWithNodes = function (sourceFile, startNode, endNode, newNodes, options) {
- if (options === void 0) { options = useNonAdjustedPositions; }
- this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options);
- };
- ChangeTracker.prototype.nextCommaToken = function (sourceFile, node) {
- var next = ts.findNextToken(node, node.parent, sourceFile);
- return next && next.kind === 27 /* CommaToken */ ? next : undefined;
- };
- ChangeTracker.prototype.replacePropertyAssignment = function (sourceFile, oldNode, newNode) {
- var suffix = this.nextCommaToken(sourceFile, oldNode) ? "" : ("," + this.newLineCharacter);
- this.replaceNode(sourceFile, oldNode, newNode, { suffix: suffix });
- };
- ChangeTracker.prototype.insertNodeAt = function (sourceFile, pos, newNode, options) {
- if (options === void 0) { options = {}; }
- this.replaceRange(sourceFile, ts.createRange(pos), newNode, options);
- };
- ChangeTracker.prototype.insertNodesAt = function (sourceFile, pos, newNodes, options) {
- if (options === void 0) { options = {}; }
- this.replaceRangeWithNodes(sourceFile, ts.createRange(pos), newNodes, options);
- };
- ChangeTracker.prototype.insertNodeAtTopOfFile = function (sourceFile, newNode, blankLineBetween) {
- this.insertAtTopOfFile(sourceFile, newNode, blankLineBetween);
- };
- ChangeTracker.prototype.insertNodesAtTopOfFile = function (sourceFile, newNodes, blankLineBetween) {
- this.insertAtTopOfFile(sourceFile, newNodes, blankLineBetween);
- };
- ChangeTracker.prototype.insertAtTopOfFile = function (sourceFile, insert, blankLineBetween) {
- var pos = getInsertionPositionAtSourceFileTop(sourceFile);
- var options = {
- prefix: pos === 0 ? undefined : this.newLineCharacter,
- suffix: (ts.isLineBreak(sourceFile.text.charCodeAt(pos)) ? "" : this.newLineCharacter) + (blankLineBetween ? this.newLineCharacter : ""),
- };
- if (ts.isArray(insert)) {
- this.insertNodesAt(sourceFile, pos, insert, options);
- }
- else {
- this.insertNodeAt(sourceFile, pos, insert, options);
- }
- };
- ChangeTracker.prototype.insertFirstParameter = function (sourceFile, parameters, newParam) {
- var p0 = ts.firstOrUndefined(parameters);
- if (p0) {
- this.insertNodeBefore(sourceFile, p0, newParam);
- }
- else {
- this.insertNodeAt(sourceFile, parameters.pos, newParam);
- }
- };
- ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) {
- if (blankLineBetween === void 0) { blankLineBetween = false; }
- this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, {}), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween));
- };
- ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) {
- var pos = before.getStart(sourceFile);
- this.insertNodeAt(sourceFile, pos, ts.createToken(modifier), { suffix: " " });
- };
- ChangeTracker.prototype.insertLastModifierBefore = function (sourceFile, modifier, before) {
- if (!before.modifiers) {
- this.insertModifierBefore(sourceFile, modifier, before);
- return;
- }
- var pos = before.modifiers.end;
- this.insertNodeAt(sourceFile, pos, ts.createToken(modifier), { prefix: " " });
- };
- ChangeTracker.prototype.insertCommentBeforeLine = function (sourceFile, lineNumber, position, commentText) {
- var lineStartPosition = ts.getStartPositionOfLine(lineNumber, sourceFile);
- var startPosition = ts.getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition);
- // First try to see if we can put the comment on the previous line.
- // We need to make sure that we are not in the middle of a string literal or a comment.
- // If so, we do not want to separate the node from its comment if we can.
- // Otherwise, add an extra new line immediately before the error span.
- var insertAtLineStart = isValidLocationToAddComment(sourceFile, startPosition);
- var token = ts.getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position);
- var indent = sourceFile.text.slice(lineStartPosition, startPosition);
- var text = (insertAtLineStart ? "" : this.newLineCharacter) + "//" + commentText + this.newLineCharacter + indent;
- this.insertText(sourceFile, token.getStart(sourceFile), text);
- };
- ChangeTracker.prototype.insertJsdocCommentBefore = function (sourceFile, node, tag) {
- var fnStart = node.getStart(sourceFile);
- if (node.jsDoc) {
- for (var _i = 0, _a = node.jsDoc; _i < _a.length; _i++) {
- var jsdoc = _a[_i];
- this.deleteRange(sourceFile, {
- pos: ts.getLineStartPositionForPosition(jsdoc.getStart(sourceFile), sourceFile),
- end: getAdjustedEndPosition(sourceFile, jsdoc, /*options*/ {})
- });
- }
- }
- var startPosition = ts.getPrecedingNonSpaceCharacterPosition(sourceFile.text, fnStart - 1);
- var indent = sourceFile.text.slice(startPosition, fnStart);
- this.insertNodeAt(sourceFile, fnStart, tag, { preserveLeadingWhitespace: false, suffix: this.newLineCharacter + indent });
- };
- ChangeTracker.prototype.replaceRangeWithText = function (sourceFile, range, text) {
- this.changes.push({ kind: ChangeKind.Text, sourceFile: sourceFile, range: range, text: text });
- };
- ChangeTracker.prototype.insertText = function (sourceFile, pos, text) {
- this.replaceRangeWithText(sourceFile, ts.createRange(pos), text);
- };
- /** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */
- ChangeTracker.prototype.tryInsertTypeAnnotation = function (sourceFile, node, type) {
- var _a;
- var endNode;
- if (ts.isFunctionLike(node)) {
- endNode = ts.findChildOfKind(node, 21 /* CloseParenToken */, sourceFile);
- if (!endNode) {
- if (!ts.isArrowFunction(node))
- return false; // Function missing parentheses, give up
- // If no `)`, is an arrow function `x => x`, so use the end of the first parameter
- endNode = ts.first(node.parameters);
- }
- }
- else {
- endNode = (_a = (node.kind === 242 /* VariableDeclaration */ ? node.exclamationToken : node.questionToken)) !== null && _a !== void 0 ? _a : node.name;
- }
- this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " });
- return true;
- };
- ChangeTracker.prototype.tryInsertThisTypeAnnotation = function (sourceFile, node, type) {
- var start = ts.findChildOfKind(node, 20 /* OpenParenToken */, sourceFile).getStart(sourceFile) + 1;
- var suffix = node.parameters.length ? ", " : "";
- this.insertNodeAt(sourceFile, start, type, { prefix: "this: ", suffix: suffix });
- };
- ChangeTracker.prototype.insertTypeParameters = function (sourceFile, node, typeParameters) {
- // If no `(`, is an arrow function `x => x`, so use the pos of the first parameter
- var start = (ts.findChildOfKind(node, 20 /* OpenParenToken */, sourceFile) || ts.first(node.parameters)).getStart(sourceFile);
- this.insertNodesAt(sourceFile, start, typeParameters, { prefix: "<", suffix: ">" });
- };
- ChangeTracker.prototype.getOptionsForInsertNodeBefore = function (before, inserted, doubleNewlines) {
- if (ts.isStatement(before) || ts.isClassElement(before)) {
- return { suffix: doubleNewlines ? this.newLineCharacter + this.newLineCharacter : this.newLineCharacter };
- }
- else if (ts.isVariableDeclaration(before)) { // insert `x = 1, ` into `const x = 1, y = 2;
- return { suffix: ", " };
- }
- else if (ts.isParameter(before)) {
- return ts.isParameter(inserted) ? { suffix: ", " } : {};
- }
- else if (ts.isStringLiteral(before) && ts.isImportDeclaration(before.parent) || ts.isNamedImports(before)) {
- return { suffix: ", " };
- }
- return ts.Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it
- };
- ChangeTracker.prototype.insertNodeAtConstructorStart = function (sourceFile, ctr, newStatement) {
- var firstStatement = ts.firstOrUndefined(ctr.body.statements);
- if (!firstStatement || !ctr.body.multiLine) {
- this.replaceConstructorBody(sourceFile, ctr, __spreadArrays([newStatement], ctr.body.statements));
- }
- else {
- this.insertNodeBefore(sourceFile, firstStatement, newStatement);
- }
- };
- ChangeTracker.prototype.insertNodeAtConstructorEnd = function (sourceFile, ctr, newStatement) {
- var lastStatement = ts.lastOrUndefined(ctr.body.statements);
- if (!lastStatement || !ctr.body.multiLine) {
- this.replaceConstructorBody(sourceFile, ctr, __spreadArrays(ctr.body.statements, [newStatement]));
- }
- else {
- this.insertNodeAfter(sourceFile, lastStatement, newStatement);
- }
- };
- ChangeTracker.prototype.replaceConstructorBody = function (sourceFile, ctr, statements) {
- this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, /*multiLine*/ true));
- };
- ChangeTracker.prototype.insertNodeAtEndOfScope = function (sourceFile, scope, newNode) {
- var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {});
- this.insertNodeAt(sourceFile, pos, newNode, {
- prefix: ts.isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter,
- suffix: this.newLineCharacter
- });
- };
- ChangeTracker.prototype.insertNodeAtClassStart = function (sourceFile, cls, newElement) {
- this.insertNodeAtStartWorker(sourceFile, cls, newElement);
- };
- ChangeTracker.prototype.insertNodeAtObjectStart = function (sourceFile, obj, newElement) {
- this.insertNodeAtStartWorker(sourceFile, obj, newElement);
- };
- ChangeTracker.prototype.insertNodeAtStartWorker = function (sourceFile, cls, newElement) {
- var _a;
- var indentation = (_a = this.guessIndentationFromExistingMembers(sourceFile, cls)) !== null && _a !== void 0 ? _a : this.computeIndentationForNewMember(sourceFile, cls);
- this.insertNodeAt(sourceFile, getMembersOrProperties(cls).pos, newElement, this.getInsertNodeAtStartInsertOptions(sourceFile, cls, indentation));
- };
- /**
- * Tries to guess the indentation from the existing members of a class/interface/object. All members must be on
- * new lines and must share the same indentation.
- */
- ChangeTracker.prototype.guessIndentationFromExistingMembers = function (sourceFile, cls) {
- var indentation;
- var lastRange = cls;
- for (var _i = 0, _a = getMembersOrProperties(cls); _i < _a.length; _i++) {
- var member = _a[_i];
- if (ts.rangeStartPositionsAreOnSameLine(lastRange, member, sourceFile)) {
- // each indented member must be on a new line
- return undefined;
- }
- var memberStart = member.getStart(sourceFile);
- var memberIndentation = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(ts.getLineStartPositionForPosition(memberStart, sourceFile), memberStart, sourceFile, this.formatContext.options);
- if (indentation === undefined) {
- indentation = memberIndentation;
- }
- else if (memberIndentation !== indentation) {
- // indentation of multiple members is not consistent
- return undefined;
- }
- lastRange = member;
- }
- return indentation;
- };
- ChangeTracker.prototype.computeIndentationForNewMember = function (sourceFile, cls) {
- var _a;
- var clsStart = cls.getStart(sourceFile);
- return ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(ts.getLineStartPositionForPosition(clsStart, sourceFile), clsStart, sourceFile, this.formatContext.options)
- + ((_a = this.formatContext.options.indentSize) !== null && _a !== void 0 ? _a : 4);
- };
- ChangeTracker.prototype.getInsertNodeAtStartInsertOptions = function (sourceFile, cls, indentation) {
- // Rules:
- // - Always insert leading newline.
- // - For object literals:
- // - Add a trailing comma if there are existing members in the node, or the source file is not a JSON file
- // (because trailing commas are generally illegal in a JSON file).
- // - Add a leading comma if the source file is not a JSON file, there are existing insertions,
- // and the node is empty (because we didn't add a trailing comma per the previous rule).
- // - Only insert a trailing newline if body is single-line and there are no other insertions for the node.
- // NOTE: This is handled in `finishClassesWithNodesInsertedAtStart`.
- var members = getMembersOrProperties(cls);
- var isEmpty = members.length === 0;
- var isFirstInsertion = ts.addToSeen(this.classesWithNodesInsertedAtStart, ts.getNodeId(cls), { node: cls, sourceFile: sourceFile });
- var insertTrailingComma = ts.isObjectLiteralExpression(cls) && (!ts.isJsonSourceFile(sourceFile) || !isEmpty);
- var insertLeadingComma = ts.isObjectLiteralExpression(cls) && ts.isJsonSourceFile(sourceFile) && isEmpty && !isFirstInsertion;
- return {
- indentation: indentation,
- prefix: (insertLeadingComma ? "," : "") + this.newLineCharacter,
- suffix: insertTrailingComma ? "," : ""
- };
- };
- ChangeTracker.prototype.insertNodeAfterComma = function (sourceFile, after, newNode) {
- var endPosition = this.insertNodeAfterWorker(sourceFile, this.nextCommaToken(sourceFile, after) || after, newNode);
- this.insertNodeAt(sourceFile, endPosition, newNode, this.getInsertNodeAfterOptions(sourceFile, after));
- };
- ChangeTracker.prototype.insertNodeAfter = function (sourceFile, after, newNode) {
- var endPosition = this.insertNodeAfterWorker(sourceFile, after, newNode);
- this.insertNodeAt(sourceFile, endPosition, newNode, this.getInsertNodeAfterOptions(sourceFile, after));
- };
- ChangeTracker.prototype.insertNodeAtEndOfList = function (sourceFile, list, newNode) {
- this.insertNodeAt(sourceFile, list.end, newNode, { prefix: ", " });
- };
- ChangeTracker.prototype.insertNodesAfter = function (sourceFile, after, newNodes) {
- var endPosition = this.insertNodeAfterWorker(sourceFile, after, ts.first(newNodes));
- this.insertNodesAt(sourceFile, endPosition, newNodes, this.getInsertNodeAfterOptions(sourceFile, after));
- };
- ChangeTracker.prototype.insertNodeAfterWorker = function (sourceFile, after, newNode) {
- if (needSemicolonBetween(after, newNode)) {
- // check if previous statement ends with semicolon
- // if not - insert semicolon to preserve the code from changing the meaning due to ASI
- if (sourceFile.text.charCodeAt(after.end - 1) !== 59 /* semicolon */) {
- this.replaceRange(sourceFile, ts.createRange(after.end), ts.createToken(26 /* SemicolonToken */));
- }
- }
- var endPosition = getAdjustedEndPosition(sourceFile, after, {});
- return endPosition;
- };
- ChangeTracker.prototype.getInsertNodeAfterOptions = function (sourceFile, after) {
- var options = this.getInsertNodeAfterOptionsWorker(after);
- return __assign(__assign({}, options), { prefix: after.end === sourceFile.end && ts.isStatement(after) ? (options.prefix ? "\n" + options.prefix : "\n") : options.prefix });
- };
- ChangeTracker.prototype.getInsertNodeAfterOptionsWorker = function (node) {
- switch (node.kind) {
- case 245 /* ClassDeclaration */:
- case 249 /* ModuleDeclaration */:
- return { prefix: this.newLineCharacter, suffix: this.newLineCharacter };
- case 242 /* VariableDeclaration */:
- case 10 /* StringLiteral */:
- case 75 /* Identifier */:
- return { prefix: ", " };
- case 281 /* PropertyAssignment */:
- return { suffix: "," + this.newLineCharacter };
- case 89 /* ExportKeyword */:
- return { prefix: " " };
- case 156 /* Parameter */:
- return {};
- default:
- ts.Debug.assert(ts.isStatement(node) || ts.isClassOrTypeElement(node)); // Else we haven't handled this kind of node yet -- add it
- return { suffix: this.newLineCharacter };
- }
- };
- ChangeTracker.prototype.insertName = function (sourceFile, node, name) {
- ts.Debug.assert(!node.name);
- if (node.kind === 202 /* ArrowFunction */) {
- var arrow = ts.findChildOfKind(node, 38 /* EqualsGreaterThanToken */, sourceFile);
- var lparen = ts.findChildOfKind(node, 20 /* OpenParenToken */, sourceFile);
- if (lparen) {
- // `() => {}` --> `function f() {}`
- this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [ts.createToken(94 /* FunctionKeyword */), ts.createIdentifier(name)], { joiner: " " });
- deleteNode(this, sourceFile, arrow);
- }
- else {
- // `x => {}` -> `function f(x) {}`
- this.insertText(sourceFile, ts.first(node.parameters).getStart(sourceFile), "function " + name + "(");
- // Replacing full range of arrow to get rid of the leading space -- replace ` =>` with `)`
- this.replaceRange(sourceFile, arrow, ts.createToken(21 /* CloseParenToken */));
- }
- if (node.body.kind !== 223 /* Block */) {
- // `() => 0` => `function f() { return 0; }`
- this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [ts.createToken(18 /* OpenBraceToken */), ts.createToken(101 /* ReturnKeyword */)], { joiner: " ", suffix: " " });
- this.insertNodesAt(sourceFile, node.body.end, [ts.createToken(26 /* SemicolonToken */), ts.createToken(19 /* CloseBraceToken */)], { joiner: " " });
- }
- }
- else {
- var pos = ts.findChildOfKind(node, node.kind === 201 /* FunctionExpression */ ? 94 /* FunctionKeyword */ : 80 /* ClassKeyword */, sourceFile).end;
- this.insertNodeAt(sourceFile, pos, ts.createIdentifier(name), { prefix: " " });
- }
- };
- ChangeTracker.prototype.insertExportModifier = function (sourceFile, node) {
- this.insertText(sourceFile, node.getStart(sourceFile), "export ");
- };
- /**
- * This function should be used to insert nodes in lists when nodes don't carry separators as the part of the node range,
- * i.e. arguments in arguments lists, parameters in parameter lists etc.
- * Note that separators are part of the node in statements and class elements.
- */
- ChangeTracker.prototype.insertNodeInListAfter = function (sourceFile, after, newNode, containingList) {
- if (containingList === void 0) { containingList = ts.formatting.SmartIndenter.getContainingList(after, sourceFile); }
- if (!containingList) {
- ts.Debug.fail("node is not a list element");
- return;
- }
- var index = ts.indexOfNode(containingList, after);
- if (index < 0) {
- return;
- }
- var end = after.getEnd();
- if (index !== containingList.length - 1) {
- // any element except the last one
- // use next sibling as an anchor
- var nextToken = ts.getTokenAtPosition(sourceFile, after.end);
- if (nextToken && isSeparator(after, nextToken)) {
- // for list
- // a, b, c
- // create change for adding 'e' after 'a' as
- // - find start of next element after a (it is b)
- // - use this start as start and end position in final change
- // - build text of change by formatting the text of node + separator + whitespace trivia of b
- // in multiline case it will work as
- // a,
- // b,
- // c,
- // result - '*' denotes leading trivia that will be inserted after new text (displayed as '#')
- // a,*
- // ***insertedtext#
- // ###b,
- // c,
- // find line and character of the next element
- var lineAndCharOfNextElement = ts.getLineAndCharacterOfPosition(sourceFile, skipWhitespacesAndLineBreaks(sourceFile.text, containingList[index + 1].getFullStart()));
- // find line and character of the token that precedes next element (usually it is separator)
- var lineAndCharOfNextToken = ts.getLineAndCharacterOfPosition(sourceFile, nextToken.end);
- var prefix = void 0;
- var startPos = void 0;
- if (lineAndCharOfNextToken.line === lineAndCharOfNextElement.line) {
- // next element is located on the same line with separator:
- // a,$$$$b
- // ^ ^
- // | |-next element
- // |-separator
- // where $$$ is some leading trivia
- // for a newly inserted node we'll maintain the same relative position comparing to separator and replace leading trivia with spaces
- // a, x,$$$$b
- // ^ ^ ^
- // | | |-next element
- // | |-new inserted node padded with spaces
- // |-separator
- startPos = nextToken.end;
- prefix = spaces(lineAndCharOfNextElement.character - lineAndCharOfNextToken.character);
- }
- else {
- // next element is located on different line that separator
- // let insert position be the beginning of the line that contains next element
- startPos = ts.getStartPositionOfLine(lineAndCharOfNextElement.line, sourceFile);
- }
- // write separator and leading trivia of the next element as suffix
- var suffix = "" + ts.tokenToString(nextToken.kind) + sourceFile.text.substring(nextToken.end, containingList[index + 1].getStart(sourceFile));
- this.replaceRange(sourceFile, ts.createRange(startPos, containingList[index + 1].getStart(sourceFile)), newNode, { prefix: prefix, suffix: suffix });
- }
- }
- else {
- var afterStart = after.getStart(sourceFile);
- var afterStartLinePosition = ts.getLineStartPositionForPosition(afterStart, sourceFile);
- var separator = void 0;
- var multilineList = false;
- // insert element after the last element in the list that has more than one item
- // pick the element preceding the after element to:
- // - pick the separator
- // - determine if list is a multiline
- if (containingList.length === 1) {
- // if list has only one element then we'll format is as multiline if node has comment in trailing trivia, or as singleline otherwise
- // i.e. var x = 1 // this is x
- // | new element will be inserted at this position
- separator = 27 /* CommaToken */;
- }
- else {
- // element has more than one element, pick separator from the list
- var tokenBeforeInsertPosition = ts.findPrecedingToken(after.pos, sourceFile);
- separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : 27 /* CommaToken */;
- // determine if list is multiline by checking lines of after element and element that precedes it.
- var afterMinusOneStartLinePosition = ts.getLineStartPositionForPosition(containingList[index - 1].getStart(sourceFile), sourceFile);
- multilineList = afterMinusOneStartLinePosition !== afterStartLinePosition;
- }
- if (hasCommentsBeforeLineBreak(sourceFile.text, after.end)) {
- // in this case we'll always treat containing list as multiline
- multilineList = true;
- }
- if (multilineList) {
- // insert separator immediately following the 'after' node to preserve comments in trailing trivia
- this.replaceRange(sourceFile, ts.createRange(end), ts.createToken(separator));
- // use the same indentation as 'after' item
- var indentation = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options);
- // insert element before the line break on the line that contains 'after' element
- var insertPos = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false);
- if (insertPos !== end && ts.isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) {
- insertPos--;
- }
- this.replaceRange(sourceFile, ts.createRange(insertPos), newNode, { indentation: indentation, prefix: this.newLineCharacter });
- }
- else {
- this.replaceRange(sourceFile, ts.createRange(end), newNode, { prefix: ts.tokenToString(separator) + " " });
- }
- }
- };
- ChangeTracker.prototype.parenthesizeExpression = function (sourceFile, expression) {
- this.replaceRange(sourceFile, ts.rangeOfNode(expression), ts.createParen(expression));
- };
- ChangeTracker.prototype.finishClassesWithNodesInsertedAtStart = function () {
- var _this = this;
- this.classesWithNodesInsertedAtStart.forEach(function (_a) {
- var node = _a.node, sourceFile = _a.sourceFile;
- var _b = getClassOrObjectBraceEnds(node, sourceFile), openBraceEnd = _b[0], closeBraceEnd = _b[1];
- if (openBraceEnd !== undefined && closeBraceEnd !== undefined) {
- var isEmpty = getMembersOrProperties(node).length === 0;
- var isSingleLine = ts.positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile);
- if (isEmpty && isSingleLine && openBraceEnd !== closeBraceEnd - 1) {
- // For `class C { }` remove the whitespace inside the braces.
- _this.deleteRange(sourceFile, ts.createRange(openBraceEnd, closeBraceEnd - 1));
- }
- if (isSingleLine) {
- _this.insertText(sourceFile, closeBraceEnd - 1, _this.newLineCharacter);
- }
- }
- });
- };
- ChangeTracker.prototype.finishDeleteDeclarations = function () {
- var _this = this;
- var deletedNodesInLists = new ts.NodeSet(); // Stores nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`.
- var _loop_9 = function (sourceFile, node) {
- if (!this_1.deletedNodes.some(function (d) { return d.sourceFile === sourceFile && ts.rangeContainsRangeExclusive(d.node, node); })) {
- if (ts.isArray(node)) {
- this_1.deleteRange(sourceFile, ts.rangeOfTypeParameters(node));
- }
- else {
- deleteDeclaration.deleteDeclaration(this_1, deletedNodesInLists, sourceFile, node);
- }
- }
- };
- var this_1 = this;
- for (var _i = 0, _a = this.deletedNodes; _i < _a.length; _i++) {
- var _b = _a[_i], sourceFile = _b.sourceFile, node = _b.node;
- _loop_9(sourceFile, node);
- }
- deletedNodesInLists.forEach(function (node) {
- var sourceFile = node.getSourceFile();
- var list = ts.formatting.SmartIndenter.getContainingList(node, sourceFile);
- if (node !== ts.last(list))
- return;
- var lastNonDeletedIndex = ts.findLastIndex(list, function (n) { return !deletedNodesInLists.has(n); }, list.length - 2);
- if (lastNonDeletedIndex !== -1) {
- _this.deleteRange(sourceFile, { pos: list[lastNonDeletedIndex].end, end: startPositionToDeleteNodeInList(sourceFile, list[lastNonDeletedIndex + 1]) });
- }
- });
- };
- /**
- * Note: after calling this, the TextChanges object must be discarded!
- * @param validate only for tests
- * The reason we must validate as part of this method is that `getNonFormattedText` changes the node's positions,
- * so we can only call this once and can't get the non-formatted text separately.
- */
- ChangeTracker.prototype.getChanges = function (validate) {
- this.finishDeleteDeclarations();
- this.finishClassesWithNodesInsertedAtStart();
- var changes = changesToText.getTextChangesFromChanges(this.changes, this.newLineCharacter, this.formatContext, validate);
- for (var _i = 0, _a = this.newFiles; _i < _a.length; _i++) {
- var _b = _a[_i], oldFile = _b.oldFile, fileName = _b.fileName, statements = _b.statements;
- changes.push(changesToText.newFileChanges(oldFile, fileName, statements, this.newLineCharacter, this.formatContext));
- }
- return changes;
- };
- ChangeTracker.prototype.createNewFile = function (oldFile, fileName, statements) {
- this.newFiles.push({ oldFile: oldFile, fileName: fileName, statements: statements });
- };
- return ChangeTracker;
- }());
- textChanges_3.ChangeTracker = ChangeTracker;
- // find first non-whitespace position in the leading trivia of the node
- function startPositionToDeleteNodeInList(sourceFile, node) {
- return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
- }
- function getClassOrObjectBraceEnds(cls, sourceFile) {
- var open = ts.findChildOfKind(cls, 18 /* OpenBraceToken */, sourceFile);
- var close = ts.findChildOfKind(cls, 19 /* CloseBraceToken */, sourceFile);
- return [open === null || open === void 0 ? void 0 : open.end, close === null || close === void 0 ? void 0 : close.end];
- }
- function getMembersOrProperties(cls) {
- return ts.isObjectLiteralExpression(cls) ? cls.properties : cls.members;
- }
- function getNewFileText(statements, scriptKind, newLineCharacter, formatContext) {
- return changesToText.newFileChangesWorker(/*oldFile*/ undefined, scriptKind, statements, newLineCharacter, formatContext);
- }
- textChanges_3.getNewFileText = getNewFileText;
- var changesToText;
- (function (changesToText) {
- function getTextChangesFromChanges(changes, newLineCharacter, formatContext, validate) {
- return ts.mapDefined(ts.group(changes, function (c) { return c.sourceFile.path; }), function (changesInFile) {
- var sourceFile = changesInFile[0].sourceFile;
- // order changes by start position
- // If the start position is the same, put the shorter range first, since an empty range (x, x) may precede (x, y) but not vice-versa.
- var normalized = ts.stableSort(changesInFile, function (a, b) { return (a.range.pos - b.range.pos) || (a.range.end - b.range.end); });
- var _loop_10 = function (i) {
- ts.Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", function () {
- return JSON.stringify(normalized[i].range) + " and " + JSON.stringify(normalized[i + 1].range);
- });
- };
- // verify that change intervals do not overlap, except possibly at end points.
- for (var i = 0; i < normalized.length - 1; i++) {
- _loop_10(i);
- }
- var textChanges = ts.mapDefined(normalized, function (c) {
- var span = ts.createTextSpanFromRange(c.range);
- var newText = computeNewText(c, sourceFile, newLineCharacter, formatContext, validate);
- // Filter out redundant changes.
- if (span.length === newText.length && ts.stringContainsAt(sourceFile.text, newText, span.start)) {
- return undefined;
- }
- return ts.createTextChange(span, newText);
- });
- return textChanges.length > 0 ? { fileName: sourceFile.fileName, textChanges: textChanges } : undefined;
- });
- }
- changesToText.getTextChangesFromChanges = getTextChangesFromChanges;
- function newFileChanges(oldFile, fileName, statements, newLineCharacter, formatContext) {
- var text = newFileChangesWorker(oldFile, ts.getScriptKindFromFileName(fileName), statements, newLineCharacter, formatContext);
- return { fileName: fileName, textChanges: [ts.createTextChange(ts.createTextSpan(0, 0), text)], isNewFile: true };
- }
- changesToText.newFileChanges = newFileChanges;
- function newFileChangesWorker(oldFile, scriptKind, statements, newLineCharacter, formatContext) {
- // TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this
- var nonFormattedText = statements.map(function (s) { return getNonformattedText(s, oldFile, newLineCharacter).text; }).join(newLineCharacter);
- var sourceFile = ts.createSourceFile("any file name", nonFormattedText, 99 /* ESNext */, /*setParentNodes*/ true, scriptKind);
- var changes = ts.formatting.formatDocument(sourceFile, formatContext);
- return applyChanges(nonFormattedText, changes) + newLineCharacter;
- }
- changesToText.newFileChangesWorker = newFileChangesWorker;
- function computeNewText(change, sourceFile, newLineCharacter, formatContext, validate) {
- if (change.kind === ChangeKind.Remove) {
- return "";
- }
- if (change.kind === ChangeKind.Text) {
- return change.text;
- }
- var _a = change.options, options = _a === void 0 ? {} : _a, pos = change.range.pos;
- var format = function (n) { return getFormattedTextOfNode(n, sourceFile, pos, options, newLineCharacter, formatContext, validate); };
- var text = change.kind === ChangeKind.ReplaceWithMultipleNodes
- ? change.nodes.map(function (n) { return ts.removeSuffix(format(n), newLineCharacter); }).join(change.options.joiner || newLineCharacter) // TODO: GH#18217
- : format(change.node);
- // strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line
- var noIndent = (options.preserveLeadingWhitespace || options.indentation !== undefined || ts.getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, "");
- return (options.prefix || "") + noIndent
- + ((!options.suffix || ts.endsWith(noIndent, options.suffix))
- ? "" : options.suffix);
- }
- function getFormatCodeSettingsForWriting(_a, sourceFile) {
- var options = _a.options;
- var shouldAutoDetectSemicolonPreference = !options.semicolons || options.semicolons === ts.SemicolonPreference.Ignore;
- var shouldRemoveSemicolons = options.semicolons === ts.SemicolonPreference.Remove || shouldAutoDetectSemicolonPreference && !ts.probablyUsesSemicolons(sourceFile);
- return __assign(__assign({}, options), { semicolons: shouldRemoveSemicolons ? ts.SemicolonPreference.Remove : ts.SemicolonPreference.Ignore });
- }
- /** Note: this may mutate `nodeIn`. */
- function getFormattedTextOfNode(nodeIn, sourceFile, pos, _a, newLineCharacter, formatContext, validate) {
- var indentation = _a.indentation, prefix = _a.prefix, delta = _a.delta;
- var _b = getNonformattedText(nodeIn, sourceFile, newLineCharacter), node = _b.node, text = _b.text;
- if (validate)
- validate(node, text);
- var formatOptions = getFormatCodeSettingsForWriting(formatContext, sourceFile);
- var initialIndentation = indentation !== undefined
- ? indentation
- : ts.formatting.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, prefix === newLineCharacter || ts.getLineStartPositionForPosition(pos, sourceFile) === pos);
- if (delta === undefined) {
- delta = ts.formatting.SmartIndenter.shouldIndentChildNode(formatOptions, nodeIn) ? (formatOptions.indentSize || 0) : 0;
- }
- var file = { text: text, getLineAndCharacterOfPosition: function (pos) { return ts.getLineAndCharacterOfPosition(this, pos); } };
- var changes = ts.formatting.formatNodeGivenIndentation(node, file, sourceFile.languageVariant, initialIndentation, delta, __assign(__assign({}, formatContext), { options: formatOptions }));
- return applyChanges(text, changes);
- }
- /** Note: output node may be mutated input node. */
- function getNonformattedText(node, sourceFile, newLineCharacter) {
- var writer = createWriter(newLineCharacter);
- var newLine = newLineCharacter === "\n" ? 1 /* LineFeed */ : 0 /* CarriageReturnLineFeed */;
- ts.createPrinter({ newLine: newLine, neverAsciiEscape: true, preserveSourceNewlines: true }, writer).writeNode(4 /* Unspecified */, node, sourceFile, writer);
- return { text: writer.getText(), node: assignPositionsToNode(node) };
- }
- changesToText.getNonformattedText = getNonformattedText;
- })(changesToText || (changesToText = {}));
- function applyChanges(text, changes) {
- for (var i = changes.length - 1; i >= 0; i--) {
- var _a = changes[i], span = _a.span, newText = _a.newText;
- text = "" + text.substring(0, span.start) + newText + text.substring(ts.textSpanEnd(span));
- }
- return text;
- }
- textChanges_3.applyChanges = applyChanges;
- function isTrivia(s) {
- return ts.skipTrivia(s, 0) === s.length;
- }
- function assignPositionsToNode(node) {
- var visited = ts.visitEachChild(node, assignPositionsToNode, ts.nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); // TODO: GH#18217
- // create proxy node for non synthesized nodes
- var newNode = ts.nodeIsSynthesized(visited) ? visited : Object.create(visited);
- newNode.pos = getPos(node);
- newNode.end = getEnd(node);
- return newNode;
- }
- function assignPositionsToNodeArray(nodes, visitor, test, start, count) {
- var visited = ts.visitNodes(nodes, visitor, test, start, count);
- if (!visited) {
- return visited;
- }
- // clone nodearray if necessary
- var nodeArray = visited === nodes ? ts.createNodeArray(visited.slice(0)) : visited;
- nodeArray.pos = getPos(nodes);
- nodeArray.end = getEnd(nodes);
- return nodeArray;
- }
- function createWriter(newLine) {
- var lastNonTriviaPosition = 0;
- var writer = ts.createTextWriter(newLine);
- var onEmitNode = function (hint, node, printCallback) {
- if (node) {
- setPos(node, lastNonTriviaPosition);
- }
- printCallback(hint, node);
- if (node) {
- setEnd(node, lastNonTriviaPosition);
- }
- };
- var onBeforeEmitNodeArray = function (nodes) {
- if (nodes) {
- setPos(nodes, lastNonTriviaPosition);
- }
- };
- var onAfterEmitNodeArray = function (nodes) {
- if (nodes) {
- setEnd(nodes, lastNonTriviaPosition);
- }
- };
- var onBeforeEmitToken = function (node) {
- if (node) {
- setPos(node, lastNonTriviaPosition);
- }
- };
- var onAfterEmitToken = function (node) {
- if (node) {
- setEnd(node, lastNonTriviaPosition);
- }
- };
- function setLastNonTriviaPosition(s, force) {
- if (force || !isTrivia(s)) {
- lastNonTriviaPosition = writer.getTextPos();
- var i = 0;
- while (ts.isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) {
- i++;
- }
- // trim trailing whitespaces
- lastNonTriviaPosition -= i;
- }
- }
- function write(s) {
- writer.write(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeComment(s) {
- writer.writeComment(s);
- }
- function writeKeyword(s) {
- writer.writeKeyword(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeOperator(s) {
- writer.writeOperator(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writePunctuation(s) {
- writer.writePunctuation(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeTrailingSemicolon(s) {
- writer.writeTrailingSemicolon(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeParameter(s) {
- writer.writeParameter(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeProperty(s) {
- writer.writeProperty(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeSpace(s) {
- writer.writeSpace(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeStringLiteral(s) {
- writer.writeStringLiteral(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeSymbol(s, sym) {
- writer.writeSymbol(s, sym);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeLine(force) {
- writer.writeLine(force);
- }
- function increaseIndent() {
- writer.increaseIndent();
- }
- function decreaseIndent() {
- writer.decreaseIndent();
- }
- function getText() {
- return writer.getText();
- }
- function rawWrite(s) {
- writer.rawWrite(s);
- setLastNonTriviaPosition(s, /*force*/ false);
- }
- function writeLiteral(s) {
- writer.writeLiteral(s);
- setLastNonTriviaPosition(s, /*force*/ true);
- }
- function getTextPos() {
- return writer.getTextPos();
- }
- function getLine() {
- return writer.getLine();
- }
- function getColumn() {
- return writer.getColumn();
- }
- function getIndent() {
- return writer.getIndent();
- }
- function isAtStartOfLine() {
- return writer.isAtStartOfLine();
- }
- function clear() {
- writer.clear();
- lastNonTriviaPosition = 0;
- }
- return {
- onEmitNode: onEmitNode,
- onBeforeEmitNodeArray: onBeforeEmitNodeArray,
- onAfterEmitNodeArray: onAfterEmitNodeArray,
- onBeforeEmitToken: onBeforeEmitToken,
- onAfterEmitToken: onAfterEmitToken,
- write: write,
- writeComment: writeComment,
- writeKeyword: writeKeyword,
- writeOperator: writeOperator,
- writePunctuation: writePunctuation,
- writeTrailingSemicolon: writeTrailingSemicolon,
- writeParameter: writeParameter,
- writeProperty: writeProperty,
- writeSpace: writeSpace,
- writeStringLiteral: writeStringLiteral,
- writeSymbol: writeSymbol,
- writeLine: writeLine,
- increaseIndent: increaseIndent,
- decreaseIndent: decreaseIndent,
- getText: getText,
- rawWrite: rawWrite,
- writeLiteral: writeLiteral,
- getTextPos: getTextPos,
- getLine: getLine,
- getColumn: getColumn,
- getIndent: getIndent,
- isAtStartOfLine: isAtStartOfLine,
- hasTrailingComment: function () { return writer.hasTrailingComment(); },
- hasTrailingWhitespace: function () { return writer.hasTrailingWhitespace(); },
- clear: clear
- };
- }
- function getInsertionPositionAtSourceFileTop(sourceFile) {
- var lastPrologue;
- for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) {
- var node = _a[_i];
- if (ts.isPrologueDirective(node)) {
- lastPrologue = node;
- }
- else {
- break;
- }
- }
- var position = 0;
- var text = sourceFile.text;
- if (lastPrologue) {
- position = lastPrologue.end;
- advancePastLineBreak();
- return position;
- }
- var shebang = ts.getShebang(text);
- if (shebang !== undefined) {
- position = shebang.length;
- advancePastLineBreak();
- }
- var ranges = ts.getLeadingCommentRanges(text, position);
- if (!ranges)
- return position;
- // Find the first attached comment to the first node and add before it
- var lastComment;
- var firstNodeLine;
- for (var _b = 0, ranges_1 = ranges; _b < ranges_1.length; _b++) {
- var range = ranges_1[_b];
- if (range.kind === 3 /* MultiLineCommentTrivia */) {
- if (ts.isPinnedComment(text, range.pos)) {
- lastComment = { range: range, pinnedOrTripleSlash: true };
- continue;
- }
- }
- else if (ts.isRecognizedTripleSlashComment(text, range.pos, range.end)) {
- lastComment = { range: range, pinnedOrTripleSlash: true };
- continue;
- }
- if (lastComment) {
- // Always insert after pinned or triple slash comments
- if (lastComment.pinnedOrTripleSlash)
- break;
- // There was a blank line between the last comment and this comment.
- // This comment is not part of the copyright comments
- var commentLine = sourceFile.getLineAndCharacterOfPosition(range.pos).line;
- var lastCommentEndLine = sourceFile.getLineAndCharacterOfPosition(lastComment.range.end).line;
- if (commentLine >= lastCommentEndLine + 2)
- break;
- }
- if (sourceFile.statements.length) {
- if (firstNodeLine === undefined)
- firstNodeLine = sourceFile.getLineAndCharacterOfPosition(sourceFile.statements[0].getStart()).line;
- var commentEndLine = sourceFile.getLineAndCharacterOfPosition(range.end).line;
- if (firstNodeLine < commentEndLine + 2)
- break;
- }
- lastComment = { range: range, pinnedOrTripleSlash: false };
- }
- if (lastComment) {
- position = lastComment.range.end;
- advancePastLineBreak();
- }
- return position;
- function advancePastLineBreak() {
- if (position < text.length) {
- var charCode = text.charCodeAt(position);
- if (ts.isLineBreak(charCode)) {
- position++;
- if (position < text.length && charCode === 13 /* carriageReturn */ && text.charCodeAt(position) === 10 /* lineFeed */) {
- position++;
- }
- }
- }
- }
- }
- function isValidLocationToAddComment(sourceFile, position) {
- return !ts.isInComment(sourceFile, position) && !ts.isInString(sourceFile, position) && !ts.isInTemplateString(sourceFile, position) && !ts.isInJSXText(sourceFile, position);
- }
- textChanges_3.isValidLocationToAddComment = isValidLocationToAddComment;
- function needSemicolonBetween(a, b) {
- return (ts.isPropertySignature(a) || ts.isPropertyDeclaration(a)) && ts.isClassOrTypeElement(b) && b.name.kind === 154 /* ComputedPropertyName */
- || ts.isStatementButNotDeclaration(a) && ts.isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[`
- }
- var deleteDeclaration;
- (function (deleteDeclaration_1) {
- function deleteDeclaration(changes, deletedNodesInLists, sourceFile, node) {
- switch (node.kind) {
- case 156 /* Parameter */: {
- var oldFunction = node.parent;
- if (ts.isArrowFunction(oldFunction) &&
- oldFunction.parameters.length === 1 &&
- !ts.findChildOfKind(oldFunction, 20 /* OpenParenToken */, sourceFile)) {
- // Lambdas with exactly one parameter are special because, after removal, there
- // must be an empty parameter list (i.e. `()`) and this won't necessarily be the
- // case if the parameter is simply removed (e.g. in `x => 1`).
- changes.replaceNodeWithText(sourceFile, node, "()");
- }
- else {
- deleteNodeInList(changes, deletedNodesInLists, sourceFile, node);
- }
- break;
- }
- case 254 /* ImportDeclaration */:
- case 253 /* ImportEqualsDeclaration */:
- var isFirstImport = sourceFile.imports.length && node === ts.first(sourceFile.imports).parent || node === ts.find(sourceFile.statements, ts.isAnyImportSyntax);
- // For first import, leave header comment in place, otherwise only delete JSDoc comments
- deleteNode(changes, sourceFile, node, { leadingTriviaOption: isFirstImport ? LeadingTriviaOption.Exclude : ts.hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine });
- break;
- case 191 /* BindingElement */:
- var pattern = node.parent;
- var preserveComma = pattern.kind === 190 /* ArrayBindingPattern */ && node !== ts.last(pattern.elements);
- if (preserveComma) {
- deleteNode(changes, sourceFile, node);
- }
- else {
- deleteNodeInList(changes, deletedNodesInLists, sourceFile, node);
- }
- break;
- case 242 /* VariableDeclaration */:
- deleteVariableDeclaration(changes, deletedNodesInLists, sourceFile, node);
- break;
- case 155 /* TypeParameter */:
- deleteNodeInList(changes, deletedNodesInLists, sourceFile, node);
- break;
- case 258 /* ImportSpecifier */:
- var namedImports = node.parent;
- if (namedImports.elements.length === 1) {
- deleteImportBinding(changes, sourceFile, namedImports);
- }
- else {
- deleteNodeInList(changes, deletedNodesInLists, sourceFile, node);
- }
- break;
- case 256 /* NamespaceImport */:
- deleteImportBinding(changes, sourceFile, node);
- break;
- case 26 /* SemicolonToken */:
- deleteNode(changes, sourceFile, node, { trailingTriviaOption: TrailingTriviaOption.Exclude });
- break;
- case 94 /* FunctionKeyword */:
- deleteNode(changes, sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.Exclude });
- break;
- case 245 /* ClassDeclaration */:
- case 244 /* FunctionDeclaration */:
- deleteNode(changes, sourceFile, node, { leadingTriviaOption: ts.hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine });
- break;
- default:
- if (ts.isImportClause(node.parent) && node.parent.name === node) {
- deleteDefaultImport(changes, sourceFile, node.parent);
- }
- else if (ts.isCallExpression(node.parent) && ts.contains(node.parent.arguments, node)) {
- deleteNodeInList(changes, deletedNodesInLists, sourceFile, node);
- }
- else {
- deleteNode(changes, sourceFile, node);
- }
- }
- }
- deleteDeclaration_1.deleteDeclaration = deleteDeclaration;
- function deleteDefaultImport(changes, sourceFile, importClause) {
- if (!importClause.namedBindings) {
- // Delete the whole import
- deleteNode(changes, sourceFile, importClause.parent);
- }
- else {
- // import |d,| * as ns from './file'
- var start = importClause.name.getStart(sourceFile);
- var nextToken = ts.getTokenAtPosition(sourceFile, importClause.name.end);
- if (nextToken && nextToken.kind === 27 /* CommaToken */) {
- // shift first non-whitespace position after comma to the start position of the node
- var end = ts.skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/ true);
- changes.deleteRange(sourceFile, { pos: start, end: end });
- }
- else {
- deleteNode(changes, sourceFile, importClause.name);
- }
- }
- }
- function deleteImportBinding(changes, sourceFile, node) {
- if (node.parent.name) {
- // Delete named imports while preserving the default import
- // import d|, * as ns| from './file'
- // import d|, { a }| from './file'
- var previousToken = ts.Debug.checkDefined(ts.getTokenAtPosition(sourceFile, node.pos - 1));
- changes.deleteRange(sourceFile, { pos: previousToken.getStart(sourceFile), end: node.end });
- }
- else {
- // Delete the entire import declaration
- // |import * as ns from './file'|
- // |import { a } from './file'|
- var importDecl = ts.getAncestor(node, 254 /* ImportDeclaration */);
- deleteNode(changes, sourceFile, importDecl);
- }
- }
- function deleteVariableDeclaration(changes, deletedNodesInLists, sourceFile, node) {
- var parent = node.parent;
- if (parent.kind === 280 /* CatchClause */) {
- // TODO: There's currently no unused diagnostic for this, could be a suggestion
- changes.deleteNodeRange(sourceFile, ts.findChildOfKind(parent, 20 /* OpenParenToken */, sourceFile), ts.findChildOfKind(parent, 21 /* CloseParenToken */, sourceFile));
- return;
- }
- if (parent.declarations.length !== 1) {
- deleteNodeInList(changes, deletedNodesInLists, sourceFile, node);
- return;
- }
- var gp = parent.parent;
- switch (gp.kind) {
- case 232 /* ForOfStatement */:
- case 231 /* ForInStatement */:
- changes.replaceNode(sourceFile, node, ts.createObjectLiteral());
- break;
- case 230 /* ForStatement */:
- deleteNode(changes, sourceFile, parent);
- break;
- case 225 /* VariableStatement */:
- deleteNode(changes, sourceFile, gp, { leadingTriviaOption: ts.hasJSDocNodes(gp) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine });
- break;
- default:
- ts.Debug.assertNever(gp);
- }
- }
- })(deleteDeclaration || (deleteDeclaration = {}));
- /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */
- // Exported for tests only! (TODO: improve tests to not need this)
- function deleteNode(changes, sourceFile, node, options) {
- if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; }
- var startPosition = getAdjustedStartPosition(sourceFile, node, options);
- var endPosition = getAdjustedEndPosition(sourceFile, node, options);
- changes.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
- }
- textChanges_3.deleteNode = deleteNode;
- function deleteNodeInList(changes, deletedNodesInLists, sourceFile, node) {
- var containingList = ts.Debug.checkDefined(ts.formatting.SmartIndenter.getContainingList(node, sourceFile));
- var index = ts.indexOfNode(containingList, node);
- ts.Debug.assert(index !== -1);
- if (containingList.length === 1) {
- deleteNode(changes, sourceFile, node);
- return;
- }
- // Note: We will only delete a comma *after* a node. This will leave a trailing comma if we delete the last node.
- // That's handled in the end by `finishTrailingCommaAfterDeletingNodesInList`.
- ts.Debug.assert(!deletedNodesInLists.has(node), "Deleting a node twice");
- deletedNodesInLists.add(node);
- changes.deleteRange(sourceFile, {
- pos: startPositionToDeleteNodeInList(sourceFile, node),
- end: index === containingList.length - 1 ? getAdjustedEndPosition(sourceFile, node, {}) : startPositionToDeleteNodeInList(sourceFile, containingList[index + 1]),
- });
- }
- })(textChanges = ts.textChanges || (ts.textChanges = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodeToFixes = ts.createMultiMap();
- var fixIdToRegistration = ts.createMap();
- function diagnosticToString(diag) {
- return ts.isArray(diag)
- ? ts.formatStringFromArgs(ts.getLocaleSpecificMessage(diag[0]), diag.slice(1))
- : ts.getLocaleSpecificMessage(diag);
- }
- function createCodeFixActionWithoutFixAll(fixName, changes, description) {
- return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined);
- }
- codefix.createCodeFixActionWithoutFixAll = createCodeFixActionWithoutFixAll;
- function createCodeFixAction(fixName, changes, description, fixId, fixAllDescription, command) {
- return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, fixId, diagnosticToString(fixAllDescription), command);
- }
- codefix.createCodeFixAction = createCodeFixAction;
- function createCodeFixActionWorker(fixName, description, changes, fixId, fixAllDescription, command) {
- return { fixName: fixName, description: description, changes: changes, fixId: fixId, fixAllDescription: fixAllDescription, commands: command ? [command] : undefined };
- }
- function registerCodeFix(reg) {
- for (var _i = 0, _a = reg.errorCodes; _i < _a.length; _i++) {
- var error = _a[_i];
- errorCodeToFixes.add(String(error), reg);
- }
- if (reg.fixIds) {
- for (var _b = 0, _c = reg.fixIds; _b < _c.length; _b++) {
- var fixId = _c[_b];
- ts.Debug.assert(!fixIdToRegistration.has(fixId));
- fixIdToRegistration.set(fixId, reg);
- }
- }
- }
- codefix.registerCodeFix = registerCodeFix;
- function getSupportedErrorCodes() {
- return ts.arrayFrom(errorCodeToFixes.keys());
- }
- codefix.getSupportedErrorCodes = getSupportedErrorCodes;
- function removeFixIdIfFixAllUnavailable(registration, diagnostics) {
- var errorCodes = registration.errorCodes;
- var maybeFixableDiagnostics = 0;
- for (var _i = 0, diagnostics_1 = diagnostics; _i < diagnostics_1.length; _i++) {
- var diag = diagnostics_1[_i];
- if (ts.contains(errorCodes, diag.code))
- maybeFixableDiagnostics++;
- if (maybeFixableDiagnostics > 1)
- break;
- }
- var fixAllUnavailable = maybeFixableDiagnostics < 2;
- return function (_a) {
- var fixId = _a.fixId, fixAllDescription = _a.fixAllDescription, action = __rest(_a, ["fixId", "fixAllDescription"]);
- return fixAllUnavailable ? action : __assign(__assign({}, action), { fixId: fixId, fixAllDescription: fixAllDescription });
- };
- }
- function getFixes(context) {
- var diagnostics = getDiagnostics(context);
- var registrations = errorCodeToFixes.get(String(context.errorCode));
- return ts.flatMap(registrations, function (f) { return ts.map(f.getCodeActions(context), removeFixIdIfFixAllUnavailable(f, diagnostics)); });
- }
- codefix.getFixes = getFixes;
- function getAllFixes(context) {
- // Currently fixId is always a string.
- return fixIdToRegistration.get(ts.cast(context.fixId, ts.isString)).getAllCodeActions(context);
- }
- codefix.getAllFixes = getAllFixes;
- function createCombinedCodeActions(changes, commands) {
- return { changes: changes, commands: commands };
- }
- codefix.createCombinedCodeActions = createCombinedCodeActions;
- function createFileTextChanges(fileName, textChanges) {
- return { fileName: fileName, textChanges: textChanges };
- }
- codefix.createFileTextChanges = createFileTextChanges;
- function codeFixAll(context, errorCodes, use) {
- var commands = [];
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return eachDiagnostic(context, errorCodes, function (diag) { return use(t, diag, commands); }); });
- return createCombinedCodeActions(changes, commands.length === 0 ? undefined : commands);
- }
- codefix.codeFixAll = codeFixAll;
- function eachDiagnostic(context, errorCodes, cb) {
- for (var _i = 0, _a = getDiagnostics(context); _i < _a.length; _i++) {
- var diag = _a[_i];
- if (ts.contains(errorCodes, diag.code)) {
- cb(diag);
- }
- }
- }
- codefix.eachDiagnostic = eachDiagnostic;
- function getDiagnostics(_a) {
- var program = _a.program, sourceFile = _a.sourceFile, cancellationToken = _a.cancellationToken;
- return __spreadArrays(program.getSemanticDiagnostics(sourceFile, cancellationToken), program.getSyntacticDiagnostics(sourceFile, cancellationToken), ts.computeSuggestionDiagnostics(sourceFile, program, cancellationToken));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var refactor;
- (function (refactor_1) {
- // A map with the refactor code as key, the refactor itself as value
- // e.g. nonSuggestableRefactors[refactorCode] -> the refactor you want
- var refactors = ts.createMap();
- /** @param name An unique code associated with each refactor. Does not have to be human-readable. */
- function registerRefactor(name, refactor) {
- refactors.set(name, refactor);
- }
- refactor_1.registerRefactor = registerRefactor;
- function getApplicableRefactors(context) {
- return ts.arrayFrom(ts.flatMapIterator(refactors.values(), function (refactor) {
- return context.cancellationToken && context.cancellationToken.isCancellationRequested() ? undefined : refactor.getAvailableActions(context);
- }));
- }
- refactor_1.getApplicableRefactors = getApplicableRefactors;
- function getEditsForRefactor(context, refactorName, actionName) {
- var refactor = refactors.get(refactorName);
- return refactor && refactor.getEditsForAction(context, actionName);
- }
- refactor_1.getEditsForRefactor = getEditsForRefactor;
- })(refactor = ts.refactor || (ts.refactor = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addConvertToUnknownForNonOverlappingTypes";
- var errorCodes = [ts.Diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span.start); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_unknown_conversion_for_non_overlapping_types, fixId, ts.Diagnostics.Add_unknown_to_all_conversions_of_non_overlapping_types)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag.start); }); },
- });
- function makeChange(changeTracker, sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- var assertion = ts.Debug.checkDefined(ts.findAncestor(token, function (n) { return ts.isAsExpression(n) || ts.isTypeAssertion(n); }), "Expected to find an assertion expression");
- var replacement = ts.isAsExpression(assertion)
- ? ts.createAsExpression(assertion.expression, ts.createKeywordTypeNode(148 /* UnknownKeyword */))
- : ts.createTypeAssertion(ts.createKeywordTypeNode(148 /* UnknownKeyword */), assertion.expression);
- changeTracker.replaceNode(sourceFile, assertion.expression, replacement);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- codefix.registerCodeFix({
- errorCodes: [ts.Diagnostics.await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module.code],
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var changes = ts.textChanges.ChangeTracker.with(context, function (changes) {
- var exportDeclaration = ts.createExportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.createNamedExports([]),
- /*moduleSpecifier*/ undefined,
- /*isTypeOnly*/ false);
- changes.insertNodeAtEndOfScope(sourceFile, sourceFile, exportDeclaration);
- });
- return [codefix.createCodeFixActionWithoutFixAll("addEmptyExportDeclaration", changes, ts.Diagnostics.Add_export_to_make_this_file_into_a_module)];
- },
- });
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addMissingAsync";
- var errorCodes = [
- ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code,
- ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code,
- ts.Diagnostics.Type_0_is_not_comparable_to_type_1.code
- ];
- codefix.registerCodeFix({
- fixIds: [fixId],
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, errorCode = context.errorCode, cancellationToken = context.cancellationToken, program = context.program, span = context.span;
- var diagnostic = ts.find(program.getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile, cancellationToken), getIsMatchingAsyncError(span, errorCode));
- var directSpan = diagnostic && diagnostic.relatedInformation && ts.find(diagnostic.relatedInformation, function (r) { return r.code === ts.Diagnostics.Did_you_mean_to_mark_this_function_as_async.code; });
- var decl = getFixableErrorSpanDeclaration(sourceFile, directSpan);
- if (!decl) {
- return;
- }
- var trackChanges = function (cb) { return ts.textChanges.ChangeTracker.with(context, cb); };
- return [getFix(context, decl, trackChanges)];
- },
- getAllCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var fixedDeclarations = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (t, diagnostic) {
- var span = diagnostic.relatedInformation && ts.find(diagnostic.relatedInformation, function (r) { return r.code === ts.Diagnostics.Did_you_mean_to_mark_this_function_as_async.code; });
- var decl = getFixableErrorSpanDeclaration(sourceFile, span);
- if (!decl) {
- return;
- }
- var trackChanges = function (cb) { return (cb(t), []); };
- return getFix(context, decl, trackChanges, fixedDeclarations);
- });
- },
- });
- function getFix(context, decl, trackChanges, fixedDeclarations) {
- var changes = trackChanges(function (t) { return makeChange(t, context.sourceFile, decl, fixedDeclarations); });
- return codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_async_modifier_to_containing_function, fixId, ts.Diagnostics.Add_all_missing_async_modifiers);
- }
- function makeChange(changeTracker, sourceFile, insertionSite, fixedDeclarations) {
- if (fixedDeclarations) {
- if (fixedDeclarations.has(ts.getNodeId(insertionSite).toString())) {
- return;
- }
- }
- fixedDeclarations === null || fixedDeclarations === void 0 ? void 0 : fixedDeclarations.set(ts.getNodeId(insertionSite).toString(), true);
- var cloneWithModifier = ts.getSynthesizedDeepClone(insertionSite, /*includeTrivia*/ true);
- cloneWithModifier.modifiers = ts.createNodeArray(ts.createModifiersFromModifierFlags(ts.getModifierFlags(insertionSite) | 256 /* Async */));
- cloneWithModifier.modifierFlagsCache = 0;
- changeTracker.replaceNode(sourceFile, insertionSite, cloneWithModifier);
- }
- function getFixableErrorSpanDeclaration(sourceFile, span) {
- if (!span)
- return undefined;
- var token = ts.getTokenAtPosition(sourceFile, span.start);
- // Checker has already done work to determine that async might be possible, and has attached
- // related info to the node, so start by finding the signature that exactly matches up
- // with the diagnostic range.
- var decl = ts.findAncestor(token, function (node) {
- if (node.getStart(sourceFile) < span.start || node.getEnd() > ts.textSpanEnd(span)) {
- return "quit";
- }
- return (ts.isArrowFunction(node) || ts.isMethodDeclaration(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && ts.textSpansEqual(span, ts.createTextSpanFromNode(node, sourceFile));
- });
- return decl;
- }
- function getIsMatchingAsyncError(span, errorCode) {
- return function (_a) {
- var start = _a.start, length = _a.length, relatedInformation = _a.relatedInformation, code = _a.code;
- return ts.isNumber(start) && ts.isNumber(length) && ts.textSpansEqual({ start: start, length: length }, span) &&
- code === errorCode &&
- !!relatedInformation &&
- ts.some(relatedInformation, function (related) { return related.code === ts.Diagnostics.Did_you_mean_to_mark_this_function_as_async.code; });
- };
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addMissingAwait";
- var propertyAccessCode = ts.Diagnostics.Property_0_does_not_exist_on_type_1.code;
- var callableConstructableErrorCodes = [
- ts.Diagnostics.This_expression_is_not_callable.code,
- ts.Diagnostics.This_expression_is_not_constructable.code,
- ];
- var errorCodes = __spreadArrays([
- ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type.code,
- ts.Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type.code,
- ts.Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type.code,
- ts.Diagnostics.Operator_0_cannot_be_applied_to_type_1.code,
- ts.Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2.code,
- ts.Diagnostics.This_condition_will_always_return_0_since_the_types_1_and_2_have_no_overlap.code,
- ts.Diagnostics.Type_0_is_not_an_array_type.code,
- ts.Diagnostics.Type_0_is_not_an_array_type_or_a_string_type.code,
- ts.Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_Use_compiler_option_downlevelIteration_to_allow_iterating_of_iterators.code,
- ts.Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator.code,
- ts.Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator.code,
- ts.Diagnostics.Type_0_must_have_a_Symbol_iterator_method_that_returns_an_iterator.code,
- ts.Diagnostics.Type_0_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator.code,
- ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code,
- propertyAccessCode
- ], callableConstructableErrorCodes);
- codefix.registerCodeFix({
- fixIds: [fixId],
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, errorCode = context.errorCode, span = context.span, cancellationToken = context.cancellationToken, program = context.program;
- var expression = getFixableErrorSpanExpression(sourceFile, errorCode, span, cancellationToken, program);
- if (!expression) {
- return;
- }
- var checker = context.program.getTypeChecker();
- var trackChanges = function (cb) { return ts.textChanges.ChangeTracker.with(context, cb); };
- return ts.compact([
- getDeclarationSiteFix(context, expression, errorCode, checker, trackChanges),
- getUseSiteFix(context, expression, errorCode, checker, trackChanges)
- ]);
- },
- getAllCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, cancellationToken = context.cancellationToken;
- var checker = context.program.getTypeChecker();
- var fixedDeclarations = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (t, diagnostic) {
- var expression = getFixableErrorSpanExpression(sourceFile, diagnostic.code, diagnostic, cancellationToken, program);
- if (!expression) {
- return;
- }
- var trackChanges = function (cb) { return (cb(t), []); };
- return getDeclarationSiteFix(context, expression, diagnostic.code, checker, trackChanges, fixedDeclarations)
- || getUseSiteFix(context, expression, diagnostic.code, checker, trackChanges, fixedDeclarations);
- });
- },
- });
- function getDeclarationSiteFix(context, expression, errorCode, checker, trackChanges, fixedDeclarations) {
- var sourceFile = context.sourceFile, program = context.program, cancellationToken = context.cancellationToken;
- var awaitableInitializers = findAwaitableInitializers(expression, sourceFile, cancellationToken, program, checker);
- if (awaitableInitializers) {
- var initializerChanges = trackChanges(function (t) {
- ts.forEach(awaitableInitializers.initializers, function (_a) {
- var expression = _a.expression;
- return makeChange(t, errorCode, sourceFile, checker, expression, fixedDeclarations);
- });
- if (fixedDeclarations && awaitableInitializers.needsSecondPassForFixAll) {
- makeChange(t, errorCode, sourceFile, checker, expression, fixedDeclarations);
- }
- });
- // No fix-all because it will already be included once with the use site fix,
- // and for simplicity the fix-all doesn‘t let the user choose between use-site and declaration-site fixes.
- return codefix.createCodeFixActionWithoutFixAll("addMissingAwaitToInitializer", initializerChanges, awaitableInitializers.initializers.length === 1
- ? [ts.Diagnostics.Add_await_to_initializer_for_0, awaitableInitializers.initializers[0].declarationSymbol.name]
- : ts.Diagnostics.Add_await_to_initializers);
- }
- }
- function getUseSiteFix(context, expression, errorCode, checker, trackChanges, fixedDeclarations) {
- var changes = trackChanges(function (t) { return makeChange(t, errorCode, context.sourceFile, checker, expression, fixedDeclarations); });
- return codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_await, fixId, ts.Diagnostics.Fix_all_expressions_possibly_missing_await);
- }
- function isMissingAwaitError(sourceFile, errorCode, span, cancellationToken, program) {
- var checker = program.getDiagnosticsProducingTypeChecker();
- var diagnostics = checker.getDiagnostics(sourceFile, cancellationToken);
- return ts.some(diagnostics, function (_a) {
- var start = _a.start, length = _a.length, relatedInformation = _a.relatedInformation, code = _a.code;
- return ts.isNumber(start) && ts.isNumber(length) && ts.textSpansEqual({ start: start, length: length }, span) &&
- code === errorCode &&
- !!relatedInformation &&
- ts.some(relatedInformation, function (related) { return related.code === ts.Diagnostics.Did_you_forget_to_use_await.code; });
- });
- }
- function getFixableErrorSpanExpression(sourceFile, errorCode, span, cancellationToken, program) {
- var token = ts.getTokenAtPosition(sourceFile, span.start);
- // Checker has already done work to determine that await might be possible, and has attached
- // related info to the node, so start by finding the expression that exactly matches up
- // with the diagnostic range.
- var expression = ts.findAncestor(token, function (node) {
- if (node.getStart(sourceFile) < span.start || node.getEnd() > ts.textSpanEnd(span)) {
- return "quit";
- }
- return ts.isExpression(node) && ts.textSpansEqual(span, ts.createTextSpanFromNode(node, sourceFile));
- });
- return expression
- && isMissingAwaitError(sourceFile, errorCode, span, cancellationToken, program)
- && isInsideAwaitableBody(expression) ? expression : undefined;
- }
- function findAwaitableInitializers(expression, sourceFile, cancellationToken, program, checker) {
- var identifiers = getIdentifiersFromErrorSpanExpression(expression, checker);
- if (!identifiers) {
- return;
- }
- var isCompleteFix = identifiers.isCompleteFix;
- var initializers;
- var _loop_11 = function (identifier) {
- var symbol = checker.getSymbolAtLocation(identifier);
- if (!symbol) {
- return "continue";
- }
- var declaration = ts.tryCast(symbol.valueDeclaration, ts.isVariableDeclaration);
- var variableName = declaration && ts.tryCast(declaration.name, ts.isIdentifier);
- var variableStatement = ts.getAncestor(declaration, 225 /* VariableStatement */);
- if (!declaration || !variableStatement ||
- declaration.type ||
- !declaration.initializer ||
- variableStatement.getSourceFile() !== sourceFile ||
- ts.hasModifier(variableStatement, 1 /* Export */) ||
- !variableName ||
- !isInsideAwaitableBody(declaration.initializer)) {
- isCompleteFix = false;
- return "continue";
- }
- var diagnostics = program.getSemanticDiagnostics(sourceFile, cancellationToken);
- var isUsedElsewhere = ts.FindAllReferences.Core.eachSymbolReferenceInFile(variableName, checker, sourceFile, function (reference) {
- return identifier !== reference && !symbolReferenceIsAlsoMissingAwait(reference, diagnostics, sourceFile, checker);
- });
- if (isUsedElsewhere) {
- isCompleteFix = false;
- return "continue";
- }
- (initializers || (initializers = [])).push({
- expression: declaration.initializer,
- declarationSymbol: symbol,
- });
- };
- for (var _i = 0, _a = identifiers.identifiers; _i < _a.length; _i++) {
- var identifier = _a[_i];
- _loop_11(identifier);
- }
- return initializers && {
- initializers: initializers,
- needsSecondPassForFixAll: !isCompleteFix,
- };
- }
- function getIdentifiersFromErrorSpanExpression(expression, checker) {
- if (ts.isPropertyAccessExpression(expression.parent) && ts.isIdentifier(expression.parent.expression)) {
- return { identifiers: [expression.parent.expression], isCompleteFix: true };
- }
- if (ts.isIdentifier(expression)) {
- return { identifiers: [expression], isCompleteFix: true };
- }
- if (ts.isBinaryExpression(expression)) {
- var sides = void 0;
- var isCompleteFix = true;
- for (var _i = 0, _a = [expression.left, expression.right]; _i < _a.length; _i++) {
- var side = _a[_i];
- var type = checker.getTypeAtLocation(side);
- if (checker.getPromisedTypeOfPromise(type)) {
- if (!ts.isIdentifier(side)) {
- isCompleteFix = false;
- continue;
- }
- (sides || (sides = [])).push(side);
- }
- }
- return sides && { identifiers: sides, isCompleteFix: isCompleteFix };
- }
- }
- function symbolReferenceIsAlsoMissingAwait(reference, diagnostics, sourceFile, checker) {
- var errorNode = ts.isPropertyAccessExpression(reference.parent) ? reference.parent.name :
- ts.isBinaryExpression(reference.parent) ? reference.parent :
- reference;
- var diagnostic = ts.find(diagnostics, function (diagnostic) {
- return diagnostic.start === errorNode.getStart(sourceFile) &&
- (diagnostic.start + diagnostic.length) === errorNode.getEnd();
- });
- return diagnostic && ts.contains(errorCodes, diagnostic.code) ||
- // A Promise is usually not correct in a binary expression (it’s not valid
- // in an arithmetic expression and an equality comparison seems unusual),
- // but if the other side of the binary expression has an error, the side
- // is typed `any` which will squash the error that would identify this
- // Promise as an invalid operand. So if the whole binary expression is
- // typed `any` as a result, there is a strong likelihood that this Promise
- // is accidentally missing `await`.
- checker.getTypeAtLocation(errorNode).flags & 1 /* Any */;
- }
- function isInsideAwaitableBody(node) {
- return node.kind & 32768 /* AwaitContext */ || !!ts.findAncestor(node, function (ancestor) {
- return ancestor.parent && ts.isArrowFunction(ancestor.parent) && ancestor.parent.body === ancestor ||
- ts.isBlock(ancestor) && (ancestor.parent.kind === 244 /* FunctionDeclaration */ ||
- ancestor.parent.kind === 201 /* FunctionExpression */ ||
- ancestor.parent.kind === 202 /* ArrowFunction */ ||
- ancestor.parent.kind === 161 /* MethodDeclaration */);
- });
- }
- function makeChange(changeTracker, errorCode, sourceFile, checker, insertionSite, fixedDeclarations) {
- if (ts.isBinaryExpression(insertionSite)) {
- for (var _i = 0, _a = [insertionSite.left, insertionSite.right]; _i < _a.length; _i++) {
- var side = _a[_i];
- if (fixedDeclarations && ts.isIdentifier(side)) {
- var symbol = checker.getSymbolAtLocation(side);
- if (symbol && fixedDeclarations.has(ts.getSymbolId(symbol).toString())) {
- continue;
- }
- }
- var type = checker.getTypeAtLocation(side);
- var newNode = checker.getPromisedTypeOfPromise(type) ? ts.createAwait(side) : side;
- changeTracker.replaceNode(sourceFile, side, newNode);
- }
- }
- else if (errorCode === propertyAccessCode && ts.isPropertyAccessExpression(insertionSite.parent)) {
- if (fixedDeclarations && ts.isIdentifier(insertionSite.parent.expression)) {
- var symbol = checker.getSymbolAtLocation(insertionSite.parent.expression);
- if (symbol && fixedDeclarations.has(ts.getSymbolId(symbol).toString())) {
- return;
- }
- }
- changeTracker.replaceNode(sourceFile, insertionSite.parent.expression, ts.createParen(ts.createAwait(insertionSite.parent.expression)));
- insertLeadingSemicolonIfNeeded(changeTracker, insertionSite.parent.expression, sourceFile);
- }
- else if (ts.contains(callableConstructableErrorCodes, errorCode) && ts.isCallOrNewExpression(insertionSite.parent)) {
- if (fixedDeclarations && ts.isIdentifier(insertionSite)) {
- var symbol = checker.getSymbolAtLocation(insertionSite);
- if (symbol && fixedDeclarations.has(ts.getSymbolId(symbol).toString())) {
- return;
- }
- }
- changeTracker.replaceNode(sourceFile, insertionSite, ts.createParen(ts.createAwait(insertionSite)));
- insertLeadingSemicolonIfNeeded(changeTracker, insertionSite, sourceFile);
- }
- else {
- if (fixedDeclarations && ts.isVariableDeclaration(insertionSite.parent) && ts.isIdentifier(insertionSite.parent.name)) {
- var symbol = checker.getSymbolAtLocation(insertionSite.parent.name);
- if (symbol && !ts.addToSeen(fixedDeclarations, ts.getSymbolId(symbol))) {
- return;
- }
- }
- changeTracker.replaceNode(sourceFile, insertionSite, ts.createAwait(insertionSite));
- }
- }
- function insertLeadingSemicolonIfNeeded(changeTracker, beforeNode, sourceFile) {
- var precedingToken = ts.findPrecedingToken(beforeNode.pos, sourceFile);
- if (precedingToken && ts.positionIsASICandidate(precedingToken.end, precedingToken.parent, sourceFile)) {
- changeTracker.insertText(sourceFile, beforeNode.getStart(sourceFile), ";");
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addMissingConst";
- var errorCodes = [
- ts.Diagnostics.Cannot_find_name_0.code,
- ts.Diagnostics.No_value_exists_in_scope_for_the_shorthand_property_0_Either_declare_one_or_provide_an_initializer.code
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span.start, context.program); });
- if (changes.length > 0) {
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_const_to_unresolved_variable, fixId, ts.Diagnostics.Add_const_to_all_unresolved_variables)];
- }
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var fixedNodes = new ts.NodeSet();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag.start, context.program, fixedNodes); });
- },
- });
- function makeChange(changeTracker, sourceFile, pos, program, fixedNodes) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- var forInitializer = ts.findAncestor(token, function (node) {
- return ts.isForInOrOfStatement(node.parent) ? node.parent.initializer === node :
- isPossiblyPartOfDestructuring(node) ? false : "quit";
- });
- if (forInitializer)
- return applyChange(changeTracker, forInitializer, sourceFile, fixedNodes);
- var parent = token.parent;
- if (ts.isBinaryExpression(parent) && parent.operatorToken.kind === 62 /* EqualsToken */ && ts.isExpressionStatement(parent.parent)) {
- return applyChange(changeTracker, token, sourceFile, fixedNodes);
- }
- if (ts.isArrayLiteralExpression(parent)) {
- var checker_1 = program.getTypeChecker();
- if (!ts.every(parent.elements, function (element) { return arrayElementCouldBeVariableDeclaration(element, checker_1); })) {
- return;
- }
- return applyChange(changeTracker, parent, sourceFile, fixedNodes);
- }
- var commaExpression = ts.findAncestor(token, function (node) {
- return ts.isExpressionStatement(node.parent) ? true :
- isPossiblyPartOfCommaSeperatedInitializer(node) ? false : "quit";
- });
- if (commaExpression) {
- var checker = program.getTypeChecker();
- if (!expressionCouldBeVariableDeclaration(commaExpression, checker)) {
- return;
- }
- return applyChange(changeTracker, commaExpression, sourceFile, fixedNodes);
- }
- }
- function applyChange(changeTracker, initializer, sourceFile, fixedNodes) {
- if (!fixedNodes || fixedNodes.tryAdd(initializer)) {
- changeTracker.insertModifierBefore(sourceFile, 81 /* ConstKeyword */, initializer);
- }
- }
- function isPossiblyPartOfDestructuring(node) {
- switch (node.kind) {
- case 75 /* Identifier */:
- case 192 /* ArrayLiteralExpression */:
- case 193 /* ObjectLiteralExpression */:
- case 281 /* PropertyAssignment */:
- case 282 /* ShorthandPropertyAssignment */:
- return true;
- default:
- return false;
- }
- }
- function arrayElementCouldBeVariableDeclaration(expression, checker) {
- var identifier = ts.isIdentifier(expression) ? expression :
- ts.isAssignmentExpression(expression, /*excludeCompoundAssignment*/ true) && ts.isIdentifier(expression.left) ? expression.left :
- undefined;
- return !!identifier && !checker.getSymbolAtLocation(identifier);
- }
- function isPossiblyPartOfCommaSeperatedInitializer(node) {
- switch (node.kind) {
- case 75 /* Identifier */:
- case 209 /* BinaryExpression */:
- case 27 /* CommaToken */:
- return true;
- default:
- return false;
- }
- }
- function expressionCouldBeVariableDeclaration(expression, checker) {
- if (!ts.isBinaryExpression(expression)) {
- return false;
- }
- if (expression.operatorToken.kind === 27 /* CommaToken */) {
- return ts.every([expression.left, expression.right], function (expression) { return expressionCouldBeVariableDeclaration(expression, checker); });
- }
- return expression.operatorToken.kind === 62 /* EqualsToken */
- && ts.isIdentifier(expression.left)
- && !checker.getSymbolAtLocation(expression.left);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addMissingDeclareProperty";
- var errorCodes = [
- ts.Diagnostics.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span.start); });
- if (changes.length > 0) {
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Prefix_with_declare, fixId, ts.Diagnostics.Prefix_all_incorrect_property_declarations_with_declare)];
- }
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var fixedNodes = new ts.NodeSet();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag.start, fixedNodes); });
- },
- });
- function makeChange(changeTracker, sourceFile, pos, fixedNodes) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- if (!ts.isIdentifier(token)) {
- return;
- }
- var declaration = token.parent;
- if (declaration.kind === 159 /* PropertyDeclaration */ &&
- (!fixedNodes || fixedNodes.tryAdd(declaration))) {
- changeTracker.insertModifierBefore(sourceFile, 130 /* DeclareKeyword */, declaration);
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addMissingInvocationForDecorator";
- var errorCodes = [ts.Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span.start); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Call_decorator_expression, fixId, ts.Diagnostics.Add_to_all_uncalled_decorators)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag.start); }); },
- });
- function makeChange(changeTracker, sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- var decorator = ts.findAncestor(token, ts.isDecorator);
- ts.Debug.assert(!!decorator, "Expected position to be owned by a decorator.");
- var replacement = ts.createCall(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
- changeTracker.replaceNode(sourceFile, decorator.expression, replacement);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addNameToNamelessParameter";
- var errorCodes = [ts.Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span.start); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_parameter_name, fixId, ts.Diagnostics.Add_names_to_all_parameters_without_names)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag.start); }); },
- });
- function makeChange(changeTracker, sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- if (!ts.isIdentifier(token)) {
- return ts.Debug.fail("add-name-to-nameless-parameter operates on identifiers, but got a " + ts.Debug.formatSyntaxKind(token.kind));
- }
- var param = token.parent;
- if (!ts.isParameter(param)) {
- return ts.Debug.fail("Tried to add a parameter name to a non-parameter: " + ts.Debug.formatSyntaxKind(token.kind));
- }
- var i = param.parent.parameters.indexOf(param);
- ts.Debug.assert(!param.type, "Tried to add a parameter name to a parameter that already had one.");
- ts.Debug.assert(i > -1, "Parameter not found in parent parameter list.");
- var replacement = ts.createParameter(
- /*decorators*/ undefined, param.modifiers, param.dotDotDotToken, "arg" + i, param.questionToken, ts.createTypeReferenceNode(token, /*typeArguments*/ undefined), param.initializer);
- changeTracker.replaceNode(sourceFile, token, replacement);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "annotateWithTypeFromJSDoc";
- var errorCodes = [ts.Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var decl = getDeclaration(context.sourceFile, context.span.start);
- if (!decl)
- return;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, decl); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Annotate_with_type_from_JSDoc, fixId, ts.Diagnostics.Annotate_everything_with_types_from_JSDoc)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var decl = getDeclaration(diag.file, diag.start);
- if (decl)
- doChange(changes, diag.file, decl);
- }); },
- });
- function getDeclaration(file, pos) {
- var name = ts.getTokenAtPosition(file, pos);
- // For an arrow function with no name, 'name' lands on the first parameter.
- return ts.tryCast(ts.isParameter(name.parent) ? name.parent.parent : name.parent, parameterShouldGetTypeFromJSDoc);
- }
- function parameterShouldGetTypeFromJSDoc(node) {
- return isDeclarationWithType(node) && hasUsableJSDoc(node);
- }
- codefix.parameterShouldGetTypeFromJSDoc = parameterShouldGetTypeFromJSDoc;
- function hasUsableJSDoc(decl) {
- return ts.isFunctionLikeDeclaration(decl)
- ? decl.parameters.some(hasUsableJSDoc) || (!decl.type && !!ts.getJSDocReturnType(decl))
- : !decl.type && !!ts.getJSDocType(decl);
- }
- function doChange(changes, sourceFile, decl) {
- if (ts.isFunctionLikeDeclaration(decl) && (ts.getJSDocReturnType(decl) || decl.parameters.some(function (p) { return !!ts.getJSDocType(p); }))) {
- if (!decl.typeParameters) {
- var typeParameters = ts.getJSDocTypeParameterDeclarations(decl);
- if (typeParameters.length)
- changes.insertTypeParameters(sourceFile, decl, typeParameters);
- }
- var needParens = ts.isArrowFunction(decl) && !ts.findChildOfKind(decl, 20 /* OpenParenToken */, sourceFile);
- if (needParens)
- changes.insertNodeBefore(sourceFile, ts.first(decl.parameters), ts.createToken(20 /* OpenParenToken */));
- for (var _i = 0, _a = decl.parameters; _i < _a.length; _i++) {
- var param = _a[_i];
- if (!param.type) {
- var paramType = ts.getJSDocType(param);
- if (paramType)
- changes.tryInsertTypeAnnotation(sourceFile, param, transformJSDocType(paramType));
- }
- }
- if (needParens)
- changes.insertNodeAfter(sourceFile, ts.last(decl.parameters), ts.createToken(21 /* CloseParenToken */));
- if (!decl.type) {
- var returnType = ts.getJSDocReturnType(decl);
- if (returnType)
- changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(returnType));
- }
- }
- else {
- var jsdocType = ts.Debug.checkDefined(ts.getJSDocType(decl), "A JSDocType for this declaration should exist"); // If not defined, shouldn't have been an error to fix
- ts.Debug.assert(!decl.type, "The JSDocType decl should have a type"); // If defined, shouldn't have been an error to fix.
- changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(jsdocType));
- }
- }
- function isDeclarationWithType(node) {
- return ts.isFunctionLikeDeclaration(node) ||
- node.kind === 242 /* VariableDeclaration */ ||
- node.kind === 158 /* PropertySignature */ ||
- node.kind === 159 /* PropertyDeclaration */;
- }
- function transformJSDocType(node) {
- switch (node.kind) {
- case 295 /* JSDocAllType */:
- case 296 /* JSDocUnknownType */:
- return ts.createTypeReferenceNode("any", ts.emptyArray);
- case 299 /* JSDocOptionalType */:
- return transformJSDocOptionalType(node);
- case 298 /* JSDocNonNullableType */:
- return transformJSDocType(node.type);
- case 297 /* JSDocNullableType */:
- return transformJSDocNullableType(node);
- case 301 /* JSDocVariadicType */:
- return transformJSDocVariadicType(node);
- case 300 /* JSDocFunctionType */:
- return transformJSDocFunctionType(node);
- case 169 /* TypeReference */:
- return transformJSDocTypeReference(node);
- default:
- var visited = ts.visitEachChild(node, transformJSDocType, /*context*/ undefined); // TODO: GH#18217
- ts.setEmitFlags(visited, 1 /* SingleLine */);
- return visited;
- }
- }
- function transformJSDocOptionalType(node) {
- return ts.createUnionTypeNode([ts.visitNode(node.type, transformJSDocType), ts.createTypeReferenceNode("undefined", ts.emptyArray)]);
- }
- function transformJSDocNullableType(node) {
- return ts.createUnionTypeNode([ts.visitNode(node.type, transformJSDocType), ts.createTypeReferenceNode("null", ts.emptyArray)]);
- }
- function transformJSDocVariadicType(node) {
- return ts.createArrayTypeNode(ts.visitNode(node.type, transformJSDocType));
- }
- function transformJSDocFunctionType(node) {
- return ts.createFunctionTypeNode(ts.emptyArray, node.parameters.map(transformJSDocParameter), node.type);
- }
- function transformJSDocParameter(node) {
- var index = node.parent.parameters.indexOf(node);
- var isRest = node.type.kind === 301 /* JSDocVariadicType */ && index === node.parent.parameters.length - 1; // TODO: GH#18217
- var name = node.name || (isRest ? "rest" : "arg" + index);
- var dotdotdot = isRest ? ts.createToken(25 /* DotDotDotToken */) : node.dotDotDotToken;
- return ts.createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, ts.visitNode(node.type, transformJSDocType), node.initializer);
- }
- function transformJSDocTypeReference(node) {
- var name = node.typeName;
- var args = node.typeArguments;
- if (ts.isIdentifier(node.typeName)) {
- if (ts.isJSDocIndexSignature(node)) {
- return transformJSDocIndexSignature(node);
- }
- var text = node.typeName.text;
- switch (node.typeName.text) {
- case "String":
- case "Boolean":
- case "Object":
- case "Number":
- text = text.toLowerCase();
- break;
- case "array":
- case "date":
- case "promise":
- text = text[0].toUpperCase() + text.slice(1);
- break;
- }
- name = ts.createIdentifier(text);
- if ((text === "Array" || text === "Promise") && !node.typeArguments) {
- args = ts.createNodeArray([ts.createTypeReferenceNode("any", ts.emptyArray)]);
- }
- else {
- args = ts.visitNodes(node.typeArguments, transformJSDocType);
- }
- }
- return ts.createTypeReferenceNode(name, args);
- }
- function transformJSDocIndexSignature(node) {
- var index = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- /*dotDotDotToken*/ undefined, node.typeArguments[0].kind === 140 /* NumberKeyword */ ? "n" : "s",
- /*questionToken*/ undefined, ts.createTypeReferenceNode(node.typeArguments[0].kind === 140 /* NumberKeyword */ ? "number" : "string", []),
- /*initializer*/ undefined);
- var indexSignature = ts.createTypeLiteralNode([ts.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments[1])]);
- ts.setEmitFlags(indexSignature, 1 /* SingleLine */);
- return indexSignature;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "convertFunctionToEs6Class";
- var errorCodes = [ts.Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, context.span.start, context.program.getTypeChecker()); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_function_to_an_ES2015_class, fixId, ts.Diagnostics.Convert_all_constructor_functions_to_classes)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, err) { return doChange(changes, err.file, err.start, context.program.getTypeChecker()); }); },
- });
- function doChange(changes, sourceFile, position, checker) {
- var ctorSymbol = checker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, position));
- if (!ctorSymbol || !(ctorSymbol.flags & (16 /* Function */ | 3 /* Variable */))) {
- // Bad input
- return undefined;
- }
- var ctorDeclaration = ctorSymbol.valueDeclaration;
- var precedingNode;
- var newClassDeclaration;
- switch (ctorDeclaration.kind) {
- case 244 /* FunctionDeclaration */:
- precedingNode = ctorDeclaration;
- changes.delete(sourceFile, ctorDeclaration);
- newClassDeclaration = createClassFromFunctionDeclaration(ctorDeclaration);
- break;
- case 242 /* VariableDeclaration */:
- precedingNode = ctorDeclaration.parent.parent;
- newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration);
- if (ctorDeclaration.parent.declarations.length === 1) {
- ts.copyLeadingComments(precedingNode, newClassDeclaration, sourceFile); // TODO: GH#18217
- changes.delete(sourceFile, precedingNode);
- }
- else {
- changes.delete(sourceFile, ctorDeclaration);
- }
- break;
- }
- if (!newClassDeclaration) {
- return undefined;
- }
- // Deleting a declaration only deletes JSDoc style comments, so only copy those to the new node.
- if (ts.hasJSDocNodes(ctorDeclaration)) {
- ts.copyLeadingComments(ctorDeclaration, newClassDeclaration, sourceFile);
- }
- // Because the preceding node could be touched, we need to insert nodes before delete nodes.
- changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration);
- function createClassElementsFromSymbol(symbol) {
- var memberElements = [];
- // all instance members are stored in the "member" array of symbol
- if (symbol.members) {
- symbol.members.forEach(function (member) {
- var memberElement = createClassElement(member, /*modifiers*/ undefined);
- if (memberElement) {
- memberElements.push(memberElement);
- }
- });
- }
- // all static members are stored in the "exports" array of symbol
- if (symbol.exports) {
- symbol.exports.forEach(function (member) {
- var memberElement = createClassElement(member, [ts.createToken(120 /* StaticKeyword */)]);
- if (memberElement) {
- memberElements.push(memberElement);
- }
- });
- }
- return memberElements;
- function shouldConvertDeclaration(_target, source) {
- // Right now the only thing we can convert are function expressions - other values shouldn't get
- // transformed. We can update this once ES public class properties are available.
- return ts.isFunctionLike(source);
- }
- function createClassElement(symbol, modifiers) {
- // Right now the only thing we can convert are function expressions, which are marked as methods
- if (!(symbol.flags & 8192 /* Method */)) {
- return;
- }
- var memberDeclaration = symbol.valueDeclaration;
- var assignmentBinaryExpression = memberDeclaration.parent;
- if (!shouldConvertDeclaration(memberDeclaration, assignmentBinaryExpression.right)) {
- return;
- }
- // delete the entire statement if this expression is the sole expression to take care of the semicolon at the end
- var nodeToDelete = assignmentBinaryExpression.parent && assignmentBinaryExpression.parent.kind === 226 /* ExpressionStatement */
- ? assignmentBinaryExpression.parent : assignmentBinaryExpression;
- changes.delete(sourceFile, nodeToDelete);
- if (!assignmentBinaryExpression.right) {
- return ts.createProperty([], modifiers, symbol.name, /*questionToken*/ undefined,
- /*type*/ undefined, /*initializer*/ undefined);
- }
- switch (assignmentBinaryExpression.right.kind) {
- case 201 /* FunctionExpression */: {
- var functionExpression = assignmentBinaryExpression.right;
- var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 126 /* AsyncKeyword */));
- var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
- /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body);
- ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile);
- return method;
- }
- case 202 /* ArrowFunction */: {
- var arrowFunction = assignmentBinaryExpression.right;
- var arrowFunctionBody = arrowFunction.body;
- var bodyBlock = void 0;
- // case 1: () => { return [1,2,3] }
- if (arrowFunctionBody.kind === 223 /* Block */) {
- bodyBlock = arrowFunctionBody;
- }
- // case 2: () => [1,2,3]
- else {
- bodyBlock = ts.createBlock([ts.createReturn(arrowFunctionBody)]);
- }
- var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 126 /* AsyncKeyword */));
- var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
- /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock);
- ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile);
- return method;
- }
- default: {
- // Don't try to declare members in JavaScript files
- if (ts.isSourceFileJS(sourceFile)) {
- return;
- }
- var prop = ts.createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined,
- /*type*/ undefined, assignmentBinaryExpression.right);
- ts.copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile);
- return prop;
- }
- }
- }
- }
- function createClassFromVariableDeclaration(node) {
- var initializer = node.initializer;
- if (!initializer || initializer.kind !== 201 /* FunctionExpression */) {
- return undefined;
- }
- if (node.name.kind !== 75 /* Identifier */) {
- return undefined;
- }
- var memberElements = createClassElementsFromSymbol(node.symbol);
- if (initializer.body) {
- memberElements.unshift(ts.createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body));
- }
- var modifiers = getModifierKindFromSource(precedingNode, 89 /* ExportKeyword */);
- var cls = ts.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
- /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements);
- // Don't call copyComments here because we'll already leave them in place
- return cls;
- }
- function createClassFromFunctionDeclaration(node) {
- var memberElements = createClassElementsFromSymbol(ctorSymbol);
- if (node.body) {
- memberElements.unshift(ts.createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body));
- }
- var modifiers = getModifierKindFromSource(node, 89 /* ExportKeyword */);
- var cls = ts.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
- /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements);
- // Don't call copyComments here because we'll already leave them in place
- return cls;
- }
- }
- function getModifierKindFromSource(source, kind) {
- return ts.filter(source.modifiers, function (modifier) { return modifier.kind === kind; });
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "convertToAsyncFunction";
- var errorCodes = [ts.Diagnostics.This_may_be_converted_to_an_async_function.code];
- var codeActionSucceeded = true;
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- codeActionSucceeded = true;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return convertToAsyncFunction(t, context.sourceFile, context.span.start, context.program.getTypeChecker(), context); });
- return codeActionSucceeded ? [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_to_async_function, fixId, ts.Diagnostics.Convert_all_to_async_functions)] : [];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, err) { return convertToAsyncFunction(changes, err.file, err.start, context.program.getTypeChecker(), context); }); },
- });
- var SynthBindingNameKind;
- (function (SynthBindingNameKind) {
- SynthBindingNameKind[SynthBindingNameKind["Identifier"] = 0] = "Identifier";
- SynthBindingNameKind[SynthBindingNameKind["BindingPattern"] = 1] = "BindingPattern";
- })(SynthBindingNameKind || (SynthBindingNameKind = {}));
- function convertToAsyncFunction(changes, sourceFile, position, checker, context) {
- // get the function declaration - returns a promise
- var tokenAtPosition = ts.getTokenAtPosition(sourceFile, position);
- var functionToConvert;
- // if the parent of a FunctionLikeDeclaration is a variable declaration, the convertToAsync diagnostic will be reported on the variable name
- if (ts.isIdentifier(tokenAtPosition) && ts.isVariableDeclaration(tokenAtPosition.parent) &&
- tokenAtPosition.parent.initializer && ts.isFunctionLikeDeclaration(tokenAtPosition.parent.initializer)) {
- functionToConvert = tokenAtPosition.parent.initializer;
- }
- else {
- functionToConvert = ts.tryCast(ts.getContainingFunction(ts.getTokenAtPosition(sourceFile, position)), ts.isFunctionLikeDeclaration);
- }
- if (!functionToConvert) {
- return;
- }
- var synthNamesMap = ts.createMap();
- var isInJavascript = ts.isInJSFile(functionToConvert);
- var setOfExpressionsToReturn = getAllPromiseExpressionsToReturn(functionToConvert, checker);
- var functionToConvertRenamed = renameCollidingVarNames(functionToConvert, checker, synthNamesMap, context.sourceFile);
- var returnStatements = functionToConvertRenamed.body && ts.isBlock(functionToConvertRenamed.body) ? getReturnStatementsWithPromiseHandlers(functionToConvertRenamed.body) : ts.emptyArray;
- var transformer = { checker: checker, synthNamesMap: synthNamesMap, setOfExpressionsToReturn: setOfExpressionsToReturn, isInJSFile: isInJavascript };
- if (!returnStatements.length) {
- return;
- }
- // add the async keyword
- changes.insertLastModifierBefore(sourceFile, 126 /* AsyncKeyword */, functionToConvert);
- var _loop_12 = function (returnStatement) {
- ts.forEachChild(returnStatement, function visit(node) {
- if (ts.isCallExpression(node)) {
- var newNodes = transformExpression(node, transformer);
- changes.replaceNodeWithNodes(sourceFile, returnStatement, newNodes);
- }
- else if (!ts.isFunctionLike(node)) {
- ts.forEachChild(node, visit);
- }
- });
- };
- for (var _i = 0, returnStatements_1 = returnStatements; _i < returnStatements_1.length; _i++) {
- var returnStatement = returnStatements_1[_i];
- _loop_12(returnStatement);
- }
- }
- function getReturnStatementsWithPromiseHandlers(body) {
- var res = [];
- ts.forEachReturnStatement(body, function (ret) {
- if (ts.isReturnStatementWithFixablePromiseHandler(ret))
- res.push(ret);
- });
- return res;
- }
- /*
- Finds all of the expressions of promise type that should not be saved in a variable during the refactor
- */
- function getAllPromiseExpressionsToReturn(func, checker) {
- if (!func.body) {
- return ts.createMap();
- }
- var setOfExpressionsToReturn = ts.createMap();
- ts.forEachChild(func.body, function visit(node) {
- if (isPromiseReturningCallExpression(node, checker, "then")) {
- setOfExpressionsToReturn.set(ts.getNodeId(node).toString(), true);
- ts.forEach(node.arguments, visit);
- }
- else if (isPromiseReturningCallExpression(node, checker, "catch")) {
- setOfExpressionsToReturn.set(ts.getNodeId(node).toString(), true);
- // if .catch() is the last call in the chain, move leftward in the chain until we hit something else that should be returned
- ts.forEachChild(node, visit);
- }
- else if (isPromiseTypedExpression(node, checker)) {
- setOfExpressionsToReturn.set(ts.getNodeId(node).toString(), true);
- // don't recurse here, since we won't refactor any children or arguments of the expression
- }
- else {
- ts.forEachChild(node, visit);
- }
- });
- return setOfExpressionsToReturn;
- }
- function isPromiseReturningCallExpression(node, checker, name) {
- if (!ts.isCallExpression(node))
- return false;
- var isExpressionOfName = ts.hasPropertyAccessExpressionWithName(node, name);
- var nodeType = isExpressionOfName && checker.getTypeAtLocation(node);
- return !!(nodeType && checker.getPromisedTypeOfPromise(nodeType));
- }
- function isPromiseTypedExpression(node, checker) {
- if (!ts.isExpression(node))
- return false;
- return !!checker.getPromisedTypeOfPromise(checker.getTypeAtLocation(node));
- }
- function declaredInFile(symbol, sourceFile) {
- return symbol.valueDeclaration && symbol.valueDeclaration.getSourceFile() === sourceFile;
- }
- /*
- Renaming of identifiers may be neccesary as the refactor changes scopes -
- This function collects all existing identifier names and names of identifiers that will be created in the refactor.
- It then checks for any collisions and renames them through getSynthesizedDeepClone
- */
- function renameCollidingVarNames(nodeToRename, checker, synthNamesMap, sourceFile) {
- var identsToRenameMap = ts.createMap(); // key is the symbol id
- var collidingSymbolMap = ts.createMultiMap();
- ts.forEachChild(nodeToRename, function visit(node) {
- if (!ts.isIdentifier(node)) {
- ts.forEachChild(node, visit);
- return;
- }
- var symbol = checker.getSymbolAtLocation(node);
- var isDefinedInFile = symbol && declaredInFile(symbol, sourceFile);
- if (symbol && isDefinedInFile) {
- var type = checker.getTypeAtLocation(node);
- // Note - the choice of the last call signature is arbitrary
- var lastCallSignature = getLastCallSignature(type, checker);
- var symbolIdString = ts.getSymbolId(symbol).toString();
- // If the identifier refers to a function, we want to add the new synthesized variable for the declaration. Example:
- // fetch('...').then(response => { ... })
- // will eventually become
- // const response = await fetch('...')
- // so we push an entry for 'response'.
- if (lastCallSignature && !ts.isFunctionLikeDeclaration(node.parent) && !synthNamesMap.has(symbolIdString)) {
- var firstParameter = ts.firstOrUndefined(lastCallSignature.parameters);
- var ident = firstParameter && ts.isParameter(firstParameter.valueDeclaration) && ts.tryCast(firstParameter.valueDeclaration.name, ts.isIdentifier) || ts.createOptimisticUniqueName("result");
- var synthName = getNewNameIfConflict(ident, collidingSymbolMap);
- synthNamesMap.set(symbolIdString, synthName);
- collidingSymbolMap.add(ident.text, symbol);
- }
- // We only care about identifiers that are parameters, variable declarations, or binding elements
- else if (node.parent && (ts.isParameter(node.parent) || ts.isVariableDeclaration(node.parent) || ts.isBindingElement(node.parent))) {
- var originalName = node.text;
- var collidingSymbols = collidingSymbolMap.get(originalName);
- // if the identifier name conflicts with a different identifier that we've already seen
- if (collidingSymbols && collidingSymbols.some(function (prevSymbol) { return prevSymbol !== symbol; })) {
- var newName = getNewNameIfConflict(node, collidingSymbolMap);
- identsToRenameMap.set(symbolIdString, newName.identifier);
- synthNamesMap.set(symbolIdString, newName);
- collidingSymbolMap.add(originalName, symbol);
- }
- else {
- var identifier = ts.getSynthesizedDeepClone(node);
- synthNamesMap.set(symbolIdString, createSynthIdentifier(identifier));
- collidingSymbolMap.add(originalName, symbol);
- }
- }
- }
- });
- return ts.getSynthesizedDeepCloneWithRenames(nodeToRename, /*includeTrivia*/ true, identsToRenameMap, checker);
- }
- function getNewNameIfConflict(name, originalNames) {
- var numVarsSameName = (originalNames.get(name.text) || ts.emptyArray).length;
- var identifier = numVarsSameName === 0 ? name : ts.createIdentifier(name.text + "_" + numVarsSameName);
- return createSynthIdentifier(identifier);
- }
- function silentFail() {
- codeActionSucceeded = false;
- return ts.emptyArray;
- }
- // dispatch function to recursively build the refactoring
- // should be kept up to date with isFixablePromiseHandler in suggestionDiagnostics.ts
- function transformExpression(node, transformer, prevArgName) {
- if (isPromiseReturningCallExpression(node, transformer.checker, "then")) {
- if (node.arguments.length === 0)
- return silentFail();
- return transformThen(node, transformer, prevArgName);
- }
- if (isPromiseReturningCallExpression(node, transformer.checker, "catch")) {
- if (node.arguments.length === 0)
- return silentFail();
- return transformCatch(node, transformer, prevArgName);
- }
- if (ts.isPropertyAccessExpression(node)) {
- return transformExpression(node.expression, transformer, prevArgName);
- }
- var nodeType = transformer.checker.getTypeAtLocation(node);
- if (nodeType && transformer.checker.getPromisedTypeOfPromise(nodeType)) {
- ts.Debug.assertNode(node.original.parent, ts.isPropertyAccessExpression);
- return transformPromiseExpressionOfPropertyAccess(node, transformer, prevArgName);
- }
- return silentFail();
- }
- function transformCatch(node, transformer, prevArgName) {
- var func = node.arguments[0];
- var argName = getArgBindingName(func, transformer);
- var possibleNameForVarDecl;
- /*
- If there is another call in the chain after the .catch() we are transforming, we will need to save the result of both paths (try block and catch block)
- To do this, we will need to synthesize a variable that we were not aware of while we were adding identifiers to the synthNamesMap
- We will use the prevArgName and then update the synthNamesMap with a new variable name for the next transformation step
- */
- if (prevArgName && !shouldReturn(node, transformer)) {
- if (isSynthIdentifier(prevArgName)) {
- possibleNameForVarDecl = prevArgName;
- transformer.synthNamesMap.forEach(function (val, key) {
- if (val.identifier.text === prevArgName.identifier.text) {
- var newSynthName = createUniqueSynthName(prevArgName);
- transformer.synthNamesMap.set(key, newSynthName);
- }
- });
- }
- else {
- possibleNameForVarDecl = createSynthIdentifier(ts.createOptimisticUniqueName("result"), prevArgName.types);
- }
- // We are about to write a 'let' variable declaration, but `transformExpression` for both
- // the try block and catch block will assign to this name. Setting this flag indicates
- // that future assignments should be written as `name = value` instead of `const name = value`.
- possibleNameForVarDecl.hasBeenDeclared = true;
- }
- var tryBlock = ts.createBlock(transformExpression(node.expression, transformer, possibleNameForVarDecl));
- var transformationBody = getTransformationBody(func, possibleNameForVarDecl, argName, node, transformer);
- var catchArg = argName ? isSynthIdentifier(argName) ? argName.identifier.text : argName.bindingPattern : "e";
- var catchVariableDeclaration = ts.createVariableDeclaration(catchArg);
- var catchClause = ts.createCatchClause(catchVariableDeclaration, ts.createBlock(transformationBody));
- /*
- In order to avoid an implicit any, we will synthesize a type for the declaration using the unions of the types of both paths (try block and catch block)
- */
- var varDeclList;
- var varDeclIdentifier;
- if (possibleNameForVarDecl && !shouldReturn(node, transformer)) {
- varDeclIdentifier = ts.getSynthesizedDeepClone(possibleNameForVarDecl.identifier);
- var typeArray = possibleNameForVarDecl.types;
- var unionType = transformer.checker.getUnionType(typeArray, 2 /* Subtype */);
- var unionTypeNode = transformer.isInJSFile ? undefined : transformer.checker.typeToTypeNode(unionType, /*enclosingDeclaration*/ undefined, /*flags*/ undefined);
- var varDecl = [ts.createVariableDeclaration(varDeclIdentifier, unionTypeNode)];
- varDeclList = ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList(varDecl, 1 /* Let */));
- }
- var tryStatement = ts.createTry(tryBlock, catchClause, /*finallyBlock*/ undefined);
- var destructuredResult = prevArgName && varDeclIdentifier && isSynthBindingPattern(prevArgName)
- && ts.createVariableStatement(/* modifiers */ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.getSynthesizedDeepCloneWithRenames(prevArgName.bindingPattern), /* type */ undefined, varDeclIdentifier)], 2 /* Const */));
- return ts.compact([varDeclList, tryStatement, destructuredResult]);
- }
- function createUniqueSynthName(prevArgName) {
- var renamedPrevArg = ts.createOptimisticUniqueName(prevArgName.identifier.text);
- return createSynthIdentifier(renamedPrevArg);
- }
- function transformThen(node, transformer, prevArgName) {
- var _a = node.arguments, onFulfilled = _a[0], onRejected = _a[1];
- var onFulfilledArgumentName = getArgBindingName(onFulfilled, transformer);
- var transformationBody = getTransformationBody(onFulfilled, prevArgName, onFulfilledArgumentName, node, transformer);
- if (onRejected) {
- var onRejectedArgumentName = getArgBindingName(onRejected, transformer);
- var tryBlock = ts.createBlock(transformExpression(node.expression, transformer, onFulfilledArgumentName).concat(transformationBody));
- var transformationBody2 = getTransformationBody(onRejected, prevArgName, onRejectedArgumentName, node, transformer);
- var catchArg = onRejectedArgumentName ? isSynthIdentifier(onRejectedArgumentName) ? onRejectedArgumentName.identifier.text : onRejectedArgumentName.bindingPattern : "e";
- var catchVariableDeclaration = ts.createVariableDeclaration(catchArg);
- var catchClause = ts.createCatchClause(catchVariableDeclaration, ts.createBlock(transformationBody2));
- return [ts.createTry(tryBlock, catchClause, /* finallyBlock */ undefined)];
- }
- return transformExpression(node.expression, transformer, onFulfilledArgumentName).concat(transformationBody);
- }
- /**
- * Transforms the 'x' part of `x.then(...)`, or the 'y()' part of `y().catch(...)`, where 'x' and 'y()' are Promises.
- */
- function transformPromiseExpressionOfPropertyAccess(node, transformer, prevArgName) {
- if (shouldReturn(node, transformer)) {
- return [ts.createReturn(ts.getSynthesizedDeepClone(node))];
- }
- return createVariableOrAssignmentOrExpressionStatement(prevArgName, ts.createAwait(node), /*typeAnnotation*/ undefined);
- }
- function createVariableOrAssignmentOrExpressionStatement(variableName, rightHandSide, typeAnnotation) {
- if (!variableName || isEmptyBindingName(variableName)) {
- // if there's no argName to assign to, there still might be side effects
- return [ts.createExpressionStatement(rightHandSide)];
- }
- if (isSynthIdentifier(variableName) && variableName.hasBeenDeclared) {
- // if the variable has already been declared, we don't need "let" or "const"
- return [ts.createExpressionStatement(ts.createAssignment(ts.getSynthesizedDeepClone(variableName.identifier), rightHandSide))];
- }
- return [
- ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([
- ts.createVariableDeclaration(ts.getSynthesizedDeepClone(getNode(variableName)), typeAnnotation, rightHandSide)
- ], 2 /* Const */))
- ];
- }
- function maybeAnnotateAndReturn(expressionToReturn, typeAnnotation) {
- if (typeAnnotation && expressionToReturn) {
- var name = ts.createOptimisticUniqueName("result");
- return __spreadArrays(createVariableOrAssignmentOrExpressionStatement(createSynthIdentifier(name), expressionToReturn, typeAnnotation), [
- ts.createReturn(name)
- ]);
- }
- return [ts.createReturn(expressionToReturn)];
- }
- // should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts
- function getTransformationBody(func, prevArgName, argName, parent, transformer) {
- var _a, _b, _c, _d;
- switch (func.kind) {
- case 100 /* NullKeyword */:
- // do not produce a transformed statement for a null argument
- break;
- case 75 /* Identifier */: // identifier includes undefined
- if (!argName) {
- // undefined was argument passed to promise handler
- break;
- }
- var synthCall = ts.createCall(ts.getSynthesizedDeepClone(func), /*typeArguments*/ undefined, isSynthIdentifier(argName) ? [argName.identifier] : []);
- if (shouldReturn(parent, transformer)) {
- return maybeAnnotateAndReturn(synthCall, (_a = parent.typeArguments) === null || _a === void 0 ? void 0 : _a[0]);
- }
- var type = transformer.checker.getTypeAtLocation(func);
- var callSignatures = transformer.checker.getSignaturesOfType(type, 0 /* Call */);
- if (!callSignatures.length) {
- // if identifier in handler has no call signatures, it's invalid
- return silentFail();
- }
- var returnType = callSignatures[0].getReturnType();
- var varDeclOrAssignment = createVariableOrAssignmentOrExpressionStatement(prevArgName, ts.createAwait(synthCall), (_b = parent.typeArguments) === null || _b === void 0 ? void 0 : _b[0]);
- if (prevArgName) {
- prevArgName.types.push(returnType);
- }
- return varDeclOrAssignment;
- case 201 /* FunctionExpression */:
- case 202 /* ArrowFunction */: {
- var funcBody = func.body;
- // Arrow functions with block bodies { } will enter this control flow
- if (ts.isBlock(funcBody)) {
- var refactoredStmts = [];
- var seenReturnStatement = false;
- for (var _i = 0, _e = funcBody.statements; _i < _e.length; _i++) {
- var statement = _e[_i];
- if (ts.isReturnStatement(statement)) {
- seenReturnStatement = true;
- if (ts.isReturnStatementWithFixablePromiseHandler(statement)) {
- refactoredStmts = refactoredStmts.concat(getInnerTransformationBody(transformer, [statement], prevArgName));
- }
- else {
- refactoredStmts.push.apply(refactoredStmts, maybeAnnotateAndReturn(statement.expression, (_c = parent.typeArguments) === null || _c === void 0 ? void 0 : _c[0]));
- }
- }
- else {
- refactoredStmts.push(statement);
- }
- }
- return shouldReturn(parent, transformer)
- ? refactoredStmts.map(function (s) { return ts.getSynthesizedDeepClone(s); })
- : removeReturns(refactoredStmts, prevArgName, transformer, seenReturnStatement);
- }
- else {
- var innerRetStmts = ts.isFixablePromiseHandler(funcBody) ? [ts.createReturn(funcBody)] : ts.emptyArray;
- var innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName);
- if (innerCbBody.length > 0) {
- return innerCbBody;
- }
- var type_1 = transformer.checker.getTypeAtLocation(func);
- var returnType_1 = getLastCallSignature(type_1, transformer.checker).getReturnType();
- var rightHandSide = ts.getSynthesizedDeepClone(funcBody);
- var possiblyAwaitedRightHandSide = !!transformer.checker.getPromisedTypeOfPromise(returnType_1) ? ts.createAwait(rightHandSide) : rightHandSide;
- if (!shouldReturn(parent, transformer)) {
- var transformedStatement = createVariableOrAssignmentOrExpressionStatement(prevArgName, possiblyAwaitedRightHandSide, /*typeAnnotation*/ undefined);
- if (prevArgName) {
- prevArgName.types.push(returnType_1);
- }
- return transformedStatement;
- }
- else {
- return maybeAnnotateAndReturn(possiblyAwaitedRightHandSide, (_d = parent.typeArguments) === null || _d === void 0 ? void 0 : _d[0]);
- }
- }
- }
- default:
- // If no cases apply, we've found a transformation body we don't know how to handle, so the refactoring should no-op to avoid deleting code.
- return silentFail();
- }
- return ts.emptyArray;
- }
- function getLastCallSignature(type, checker) {
- var callSignatures = checker.getSignaturesOfType(type, 0 /* Call */);
- return ts.lastOrUndefined(callSignatures);
- }
- function removeReturns(stmts, prevArgName, transformer, seenReturnStatement) {
- var ret = [];
- for (var _i = 0, stmts_1 = stmts; _i < stmts_1.length; _i++) {
- var stmt = stmts_1[_i];
- if (ts.isReturnStatement(stmt)) {
- if (stmt.expression) {
- var possiblyAwaitedExpression = isPromiseTypedExpression(stmt.expression, transformer.checker) ? ts.createAwait(stmt.expression) : stmt.expression;
- if (prevArgName === undefined) {
- ret.push(ts.createExpressionStatement(possiblyAwaitedExpression));
- }
- else {
- ret.push(ts.createVariableStatement(/*modifiers*/ undefined, (ts.createVariableDeclarationList([ts.createVariableDeclaration(getNode(prevArgName), /*type*/ undefined, possiblyAwaitedExpression)], 2 /* Const */))));
- }
- }
- }
- else {
- ret.push(ts.getSynthesizedDeepClone(stmt));
- }
- }
- // if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables
- if (!seenReturnStatement && prevArgName !== undefined) {
- ret.push(ts.createVariableStatement(/*modifiers*/ undefined, (ts.createVariableDeclarationList([ts.createVariableDeclaration(getNode(prevArgName), /*type*/ undefined, ts.createIdentifier("undefined"))], 2 /* Const */))));
- }
- return ret;
- }
- function getInnerTransformationBody(transformer, innerRetStmts, prevArgName) {
- var innerCbBody = [];
- for (var _i = 0, innerRetStmts_1 = innerRetStmts; _i < innerRetStmts_1.length; _i++) {
- var stmt = innerRetStmts_1[_i];
- ts.forEachChild(stmt, function visit(node) {
- if (ts.isCallExpression(node)) {
- var temp = transformExpression(node, transformer, prevArgName);
- innerCbBody = innerCbBody.concat(temp);
- if (innerCbBody.length > 0) {
- return;
- }
- }
- else if (!ts.isFunctionLike(node)) {
- ts.forEachChild(node, visit);
- }
- });
- }
- return innerCbBody;
- }
- function getArgBindingName(funcNode, transformer) {
- var types = [];
- var name;
- if (ts.isFunctionLikeDeclaration(funcNode)) {
- if (funcNode.parameters.length > 0) {
- var param = funcNode.parameters[0].name;
- name = getMappedBindingNameOrDefault(param);
- }
- }
- else if (ts.isIdentifier(funcNode)) {
- name = getMapEntryOrDefault(funcNode);
- }
- // return undefined argName when arg is null or undefined
- // eslint-disable-next-line no-in-operator
- if (!name || "identifier" in name && name.identifier.text === "undefined") {
- return undefined;
- }
- return name;
- function getMappedBindingNameOrDefault(bindingName) {
- if (ts.isIdentifier(bindingName))
- return getMapEntryOrDefault(bindingName);
- var elements = ts.flatMap(bindingName.elements, function (element) {
- if (ts.isOmittedExpression(element))
- return [];
- return [getMappedBindingNameOrDefault(element.name)];
- });
- return createSynthBindingPattern(bindingName, elements);
- }
- function getMapEntryOrDefault(identifier) {
- var originalNode = getOriginalNode(identifier);
- var symbol = getSymbol(originalNode);
- if (!symbol) {
- return createSynthIdentifier(identifier, types);
- }
- var mapEntry = transformer.synthNamesMap.get(ts.getSymbolId(symbol).toString());
- return mapEntry || createSynthIdentifier(identifier, types);
- }
- function getSymbol(node) {
- return node.symbol ? node.symbol : transformer.checker.getSymbolAtLocation(node);
- }
- function getOriginalNode(node) {
- return node.original ? node.original : node;
- }
- }
- function isEmptyBindingName(bindingName) {
- if (!bindingName) {
- return true;
- }
- if (isSynthIdentifier(bindingName)) {
- return !bindingName.identifier.text;
- }
- return ts.every(bindingName.elements, isEmptyBindingName);
- }
- function getNode(bindingName) {
- return isSynthIdentifier(bindingName) ? bindingName.identifier : bindingName.bindingPattern;
- }
- function createSynthIdentifier(identifier, types) {
- if (types === void 0) { types = []; }
- return { kind: 0 /* Identifier */, identifier: identifier, types: types, hasBeenDeclared: false };
- }
- function createSynthBindingPattern(bindingPattern, elements, types) {
- if (elements === void 0) { elements = ts.emptyArray; }
- if (types === void 0) { types = []; }
- return { kind: 1 /* BindingPattern */, bindingPattern: bindingPattern, elements: elements, types: types };
- }
- function isSynthIdentifier(bindingName) {
- return bindingName.kind === 0 /* Identifier */;
- }
- function isSynthBindingPattern(bindingName) {
- return bindingName.kind === 1 /* BindingPattern */;
- }
- function shouldReturn(expression, transformer) {
- return !!expression.original && transformer.setOfExpressionsToReturn.has(ts.getNodeId(expression.original).toString());
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- codefix.registerCodeFix({
- errorCodes: [ts.Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module.code],
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, preferences = context.preferences;
- var changes = ts.textChanges.ChangeTracker.with(context, function (changes) {
- var moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target, ts.getQuotePreference(sourceFile, preferences));
- if (moduleExportsChangedToDefault) {
- for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
- var importingFile = _a[_i];
- fixImportOfModuleExports(importingFile, sourceFile, changes, ts.getQuotePreference(importingFile, preferences));
- }
- }
- });
- // No support for fix-all since this applies to the whole file at once anyway.
- return [codefix.createCodeFixActionWithoutFixAll("convertToEs6Module", changes, ts.Diagnostics.Convert_to_ES6_module)];
- },
- });
- function fixImportOfModuleExports(importingFile, exportingFile, changes, quotePreference) {
- for (var _i = 0, _a = importingFile.imports; _i < _a.length; _i++) {
- var moduleSpecifier = _a[_i];
- var imported = ts.getResolvedModule(importingFile, moduleSpecifier.text);
- if (!imported || imported.resolvedFileName !== exportingFile.fileName) {
- continue;
- }
- var importNode = ts.importFromModuleSpecifier(moduleSpecifier);
- switch (importNode.kind) {
- case 253 /* ImportEqualsDeclaration */:
- changes.replaceNode(importingFile, importNode, ts.makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier, quotePreference));
- break;
- case 196 /* CallExpression */:
- if (ts.isRequireCall(importNode, /*checkArgumentIsStringLiteralLike*/ false)) {
- changes.replaceNode(importingFile, importNode, ts.createPropertyAccess(ts.getSynthesizedDeepClone(importNode), "default"));
- }
- break;
- }
- }
- }
- /** @returns Whether we converted a `module.exports =` to a default export. */
- function convertFileToEs6Module(sourceFile, checker, changes, target, quotePreference) {
- var identifiers = { original: collectFreeIdentifiers(sourceFile), additional: ts.createMap() };
- var exports = collectExportRenames(sourceFile, checker, identifiers);
- convertExportsAccesses(sourceFile, exports, changes);
- var moduleExportsChangedToDefault = false;
- for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- var moduleExportsChanged = convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, quotePreference);
- moduleExportsChangedToDefault = moduleExportsChangedToDefault || moduleExportsChanged;
- }
- return moduleExportsChangedToDefault;
- }
- function collectExportRenames(sourceFile, checker, identifiers) {
- var res = ts.createMap();
- forEachExportReference(sourceFile, function (node) {
- var _a = node.name, text = _a.text, originalKeywordKind = _a.originalKeywordKind;
- if (!res.has(text) && (originalKeywordKind !== undefined && ts.isNonContextualKeyword(originalKeywordKind)
- || checker.resolveName(text, node, 111551 /* Value */, /*excludeGlobals*/ true))) {
- // Unconditionally add an underscore in case `text` is a keyword.
- res.set(text, makeUniqueName("_" + text, identifiers));
- }
- });
- return res;
- }
- function convertExportsAccesses(sourceFile, exports, changes) {
- forEachExportReference(sourceFile, function (node, isAssignmentLhs) {
- if (isAssignmentLhs) {
- return;
- }
- var text = node.name.text;
- changes.replaceNode(sourceFile, node, ts.createIdentifier(exports.get(text) || text));
- });
- }
- function forEachExportReference(sourceFile, cb) {
- sourceFile.forEachChild(function recur(node) {
- if (ts.isPropertyAccessExpression(node) && ts.isExportsOrModuleExportsOrAlias(sourceFile, node.expression) && ts.isIdentifier(node.name)) {
- var parent = node.parent;
- cb(node, ts.isBinaryExpression(parent) && parent.left === node && parent.operatorToken.kind === 62 /* EqualsToken */);
- }
- node.forEachChild(recur);
- });
- }
- function convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, quotePreference) {
- switch (statement.kind) {
- case 225 /* VariableStatement */:
- convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target, quotePreference);
- return false;
- case 226 /* ExpressionStatement */: {
- var expression = statement.expression;
- switch (expression.kind) {
- case 196 /* CallExpression */: {
- if (ts.isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true)) {
- // For side-effecting require() call, just make a side-effecting import.
- changes.replaceNode(sourceFile, statement, ts.makeImport(/*name*/ undefined, /*namedImports*/ undefined, expression.arguments[0], quotePreference));
- }
- return false;
- }
- case 209 /* BinaryExpression */: {
- var operatorToken = expression.operatorToken;
- return operatorToken.kind === 62 /* EqualsToken */ && convertAssignment(sourceFile, checker, expression, changes, exports);
- }
- }
- }
- // falls through
- default:
- return false;
- }
- }
- function convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target, quotePreference) {
- var declarationList = statement.declarationList;
- var foundImport = false;
- var newNodes = ts.flatMap(declarationList.declarations, function (decl) {
- var name = decl.name, initializer = decl.initializer;
- if (initializer) {
- if (ts.isExportsOrModuleExportsOrAlias(sourceFile, initializer)) {
- // `const alias = module.exports;` can be removed.
- foundImport = true;
- return [];
- }
- else if (ts.isRequireCall(initializer, /*checkArgumentIsStringLiteralLike*/ true)) {
- foundImport = true;
- return convertSingleImport(sourceFile, name, initializer.arguments[0], changes, checker, identifiers, target, quotePreference);
- }
- else if (ts.isPropertyAccessExpression(initializer) && ts.isRequireCall(initializer.expression, /*checkArgumentIsStringLiteralLike*/ true)) {
- foundImport = true;
- return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0], identifiers, quotePreference);
- }
- }
- // Move it out to its own variable statement. (This will not be used if `!foundImport`)
- return ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList([decl], declarationList.flags));
- });
- if (foundImport) {
- // useNonAdjustedEndPosition to ensure we don't eat the newline after the statement.
- changes.replaceNodeWithNodes(sourceFile, statement, newNodes);
- }
- }
- /** Converts `const name = require("moduleSpecifier").propertyName` */
- function convertPropertyAccessImport(name, propertyName, moduleSpecifier, identifiers, quotePreference) {
- switch (name.kind) {
- case 189 /* ObjectBindingPattern */:
- case 190 /* ArrayBindingPattern */: {
- // `const [a, b] = require("c").d` --> `import { d } from "c"; const [a, b] = d;`
- var tmp = makeUniqueName(propertyName, identifiers);
- return [
- makeSingleImport(tmp, propertyName, moduleSpecifier, quotePreference),
- makeConst(/*modifiers*/ undefined, name, ts.createIdentifier(tmp)),
- ];
- }
- case 75 /* Identifier */:
- // `const a = require("b").c` --> `import { c as a } from "./b";
- return [makeSingleImport(name.text, propertyName, moduleSpecifier, quotePreference)];
- default:
- return ts.Debug.assertNever(name, "Convert to ES6 module got invalid syntax form " + name.kind);
- }
- }
- function convertAssignment(sourceFile, checker, assignment, changes, exports) {
- var left = assignment.left, right = assignment.right;
- if (!ts.isPropertyAccessExpression(left)) {
- return false;
- }
- if (ts.isExportsOrModuleExportsOrAlias(sourceFile, left)) {
- if (ts.isExportsOrModuleExportsOrAlias(sourceFile, right)) {
- // `const alias = module.exports;` or `module.exports = alias;` can be removed.
- changes.delete(sourceFile, assignment.parent);
- }
- else {
- var replacement = ts.isObjectLiteralExpression(right) ? tryChangeModuleExportsObject(right)
- : ts.isRequireCall(right, /*checkArgumentIsStringLiteralLike*/ true) ? convertReExportAll(right.arguments[0], checker)
- : undefined;
- if (replacement) {
- changes.replaceNodeWithNodes(sourceFile, assignment.parent, replacement[0]);
- return replacement[1];
- }
- else {
- changes.replaceRangeWithText(sourceFile, ts.createRange(left.getStart(sourceFile), right.pos), "export default");
- return true;
- }
- }
- }
- else if (ts.isExportsOrModuleExportsOrAlias(sourceFile, left.expression)) {
- convertNamedExport(sourceFile, assignment, changes, exports);
- }
- return false;
- }
- /**
- * Convert `module.exports = { ... }` to individual exports..
- * We can't always do this if the module has interesting members -- then it will be a default export instead.
- */
- function tryChangeModuleExportsObject(object) {
- var statements = ts.mapAllOrFail(object.properties, function (prop) {
- switch (prop.kind) {
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */:
- // TODO: Maybe we should handle this? See fourslash test `refactorConvertToEs6Module_export_object_shorthand.ts`.
- // falls through
- case 282 /* ShorthandPropertyAssignment */:
- case 283 /* SpreadAssignment */:
- return undefined;
- case 281 /* PropertyAssignment */:
- return !ts.isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer);
- case 161 /* MethodDeclaration */:
- return !ts.isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [ts.createToken(89 /* ExportKeyword */)], prop);
- default:
- ts.Debug.assertNever(prop, "Convert to ES6 got invalid prop kind " + prop.kind);
- }
- });
- return statements && [statements, false];
- }
- function convertNamedExport(sourceFile, assignment, changes, exports) {
- // If "originalKeywordKind" was set, this is e.g. `exports.
- var text = assignment.left.name.text;
- var rename = exports.get(text);
- if (rename !== undefined) {
- /*
- const _class = 0;
- export { _class as class };
- */
- var newNodes = [
- makeConst(/*modifiers*/ undefined, rename, assignment.right),
- makeExportDeclaration([ts.createExportSpecifier(rename, text)]),
- ];
- changes.replaceNodeWithNodes(sourceFile, assignment.parent, newNodes);
- }
- else {
- convertExportsPropertyAssignment(assignment, sourceFile, changes);
- }
- }
- function convertReExportAll(reExported, checker) {
- // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";`
- var moduleSpecifier = reExported.text;
- var moduleSymbol = checker.getSymbolAtLocation(reExported);
- var exports = moduleSymbol ? moduleSymbol.exports : ts.emptyUnderscoreEscapedMap;
- return exports.has("export=") ? [[reExportDefault(moduleSpecifier)], true] :
- !exports.has("default") ? [[reExportStar(moduleSpecifier)], false] :
- // If there's some non-default export, must include both `export *` and `export default`.
- exports.size > 1 ? [[reExportStar(moduleSpecifier), reExportDefault(moduleSpecifier)], true] : [[reExportDefault(moduleSpecifier)], true];
- }
- function reExportStar(moduleSpecifier) {
- return makeExportDeclaration(/*exportClause*/ undefined, moduleSpecifier);
- }
- function reExportDefault(moduleSpecifier) {
- return makeExportDeclaration([ts.createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier);
- }
- function convertExportsPropertyAssignment(_a, sourceFile, changes) {
- var left = _a.left, right = _a.right, parent = _a.parent;
- var name = left.name.text;
- if ((ts.isFunctionExpression(right) || ts.isArrowFunction(right) || ts.isClassExpression(right)) && (!right.name || right.name.text === name)) {
- // `exports.f = function() {}` -> `export function f() {}` -- Replace `exports.f = ` with `export `, and insert the name after `function`.
- changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, ts.createToken(89 /* ExportKeyword */), { suffix: " " });
- if (!right.name)
- changes.insertName(sourceFile, right, name);
- var semi = ts.findChildOfKind(parent, 26 /* SemicolonToken */, sourceFile);
- if (semi)
- changes.delete(sourceFile, semi);
- }
- else {
- // `exports.f = function g() {}` -> `export const f = function g() {}` -- just replace `exports.` with `export const `
- changes.replaceNodeRangeWithNodes(sourceFile, left.expression, ts.findChildOfKind(left, 24 /* DotToken */, sourceFile), [ts.createToken(89 /* ExportKeyword */), ts.createToken(81 /* ConstKeyword */)], { joiner: " ", suffix: " " });
- }
- }
- // TODO: GH#22492 this will cause an error if a change has been made inside the body of the node.
- function convertExportsDotXEquals_replaceNode(name, exported) {
- var modifiers = [ts.createToken(89 /* ExportKeyword */)];
- switch (exported.kind) {
- case 201 /* FunctionExpression */: {
- var expressionName = exported.name;
- if (expressionName && expressionName.text !== name) {
- // `exports.f = function g() {}` -> `export const f = function g() {}`
- return exportConst();
- }
- }
- // falls through
- case 202 /* ArrowFunction */:
- // `exports.f = function() {}` --> `export function f() {}`
- return functionExpressionToDeclaration(name, modifiers, exported);
- case 214 /* ClassExpression */:
- // `exports.C = class {}` --> `export class C {}`
- return classExpressionToDeclaration(name, modifiers, exported);
- default:
- return exportConst();
- }
- function exportConst() {
- // `exports.x = 0;` --> `export const x = 0;`
- return makeConst(modifiers, ts.createIdentifier(name), exported); // TODO: GH#18217
- }
- }
- /**
- * Converts `const <> = require("x");`.
- * Returns nodes that will replace the variable declaration for the commonjs import.
- * May also make use `changes` to remove qualifiers at the use sites of imports, to change `mod.x` to `x`.
- */
- function convertSingleImport(file, name, moduleSpecifier, changes, checker, identifiers, target, quotePreference) {
- switch (name.kind) {
- case 189 /* ObjectBindingPattern */: {
- var importSpecifiers = ts.mapAllOrFail(name.elements, function (e) {
- return e.dotDotDotToken || e.initializer || e.propertyName && !ts.isIdentifier(e.propertyName) || !ts.isIdentifier(e.name)
- ? undefined
- // (TODO: GH#18217)
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
- : makeImportSpecifier(e.propertyName && e.propertyName.text, e.name.text);
- });
- if (importSpecifiers) {
- return [ts.makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier, quotePreference)];
- }
- }
- // falls through -- object destructuring has an interesting pattern and must be a variable declaration
- case 190 /* ArrayBindingPattern */: {
- /*
- import x from "x";
- const [a, b, c] = x;
- */
- var tmp = makeUniqueName(codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, target), identifiers);
- return [
- ts.makeImport(ts.createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference),
- makeConst(/*modifiers*/ undefined, ts.getSynthesizedDeepClone(name), ts.createIdentifier(tmp)),
- ];
- }
- case 75 /* Identifier */:
- return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers, quotePreference);
- default:
- return ts.Debug.assertNever(name, "Convert to ES6 module got invalid name kind " + name.kind);
- }
- }
- /**
- * Convert `import x = require("x").`
- * Also converts uses like `x.y()` to `y()` and uses a named import.
- */
- function convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers, quotePreference) {
- var nameSymbol = checker.getSymbolAtLocation(name);
- // Maps from module property name to name actually used. (The same if there isn't shadowing.)
- var namedBindingsNames = ts.createMap();
- // True if there is some non-property use like `x()` or `f(x)`.
- var needDefaultImport = false;
- for (var _i = 0, _a = identifiers.original.get(name.text); _i < _a.length; _i++) {
- var use = _a[_i];
- if (checker.getSymbolAtLocation(use) !== nameSymbol || use === name) {
- // This was a use of a different symbol with the same name, due to shadowing. Ignore.
- continue;
- }
- var parent = use.parent;
- if (ts.isPropertyAccessExpression(parent)) {
- var expression = parent.expression, propertyName = parent.name.text;
- ts.Debug.assert(expression === use, "Didn't expect expression === use"); // Else shouldn't have been in `collectIdentifiers`
- var idName = namedBindingsNames.get(propertyName);
- if (idName === undefined) {
- idName = makeUniqueName(propertyName, identifiers);
- namedBindingsNames.set(propertyName, idName);
- }
- changes.replaceNode(file, parent, ts.createIdentifier(idName));
- }
- else {
- needDefaultImport = true;
- }
- }
- var namedBindings = namedBindingsNames.size === 0 ? undefined : ts.arrayFrom(ts.mapIterator(namedBindingsNames.entries(), function (_a) {
- var propertyName = _a[0], idName = _a[1];
- return ts.createImportSpecifier(propertyName === idName ? undefined : ts.createIdentifier(propertyName), ts.createIdentifier(idName));
- }));
- if (!namedBindings) {
- // If it was unused, ensure that we at least import *something*.
- needDefaultImport = true;
- }
- return [ts.makeImport(needDefaultImport ? ts.getSynthesizedDeepClone(name) : undefined, namedBindings, moduleSpecifier, quotePreference)];
- }
- // Identifiers helpers
- function makeUniqueName(name, identifiers) {
- while (identifiers.original.has(name) || identifiers.additional.has(name)) {
- name = "_" + name;
- }
- identifiers.additional.set(name, true);
- return name;
- }
- function collectFreeIdentifiers(file) {
- var map = ts.createMultiMap();
- forEachFreeIdentifier(file, function (id) { return map.add(id.text, id); });
- return map;
- }
- /**
- * A free identifier is an identifier that can be accessed through name lookup as a local variable.
- * In the expression `x.y`, `x` is a free identifier, but `y` is not.
- */
- function forEachFreeIdentifier(node, cb) {
- if (ts.isIdentifier(node) && isFreeIdentifier(node))
- cb(node);
- node.forEachChild(function (child) { return forEachFreeIdentifier(child, cb); });
- }
- function isFreeIdentifier(node) {
- var parent = node.parent;
- switch (parent.kind) {
- case 194 /* PropertyAccessExpression */:
- return parent.name !== node;
- case 191 /* BindingElement */:
- return parent.propertyName !== node;
- case 258 /* ImportSpecifier */:
- return parent.propertyName !== node;
- default:
- return true;
- }
- }
- // Node helpers
- function functionExpressionToDeclaration(name, additionalModifiers, fn) {
- return ts.createFunctionDeclaration(ts.getSynthesizedDeepClones(fn.decorators), // TODO: GH#19915 Don't think this is even legal.
- ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(fn.modifiers)), ts.getSynthesizedDeepClone(fn.asteriskToken), name, ts.getSynthesizedDeepClones(fn.typeParameters), ts.getSynthesizedDeepClones(fn.parameters), ts.getSynthesizedDeepClone(fn.type), ts.convertToFunctionBody(ts.getSynthesizedDeepClone(fn.body)));
- }
- function classExpressionToDeclaration(name, additionalModifiers, cls) {
- return ts.createClassDeclaration(ts.getSynthesizedDeepClones(cls.decorators), // TODO: GH#19915 Don't think this is even legal.
- ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(cls.modifiers)), name, ts.getSynthesizedDeepClones(cls.typeParameters), ts.getSynthesizedDeepClones(cls.heritageClauses), ts.getSynthesizedDeepClones(cls.members));
- }
- function makeSingleImport(localName, propertyName, moduleSpecifier, quotePreference) {
- return propertyName === "default"
- ? ts.makeImport(ts.createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference)
- : ts.makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference);
- }
- function makeImportSpecifier(propertyName, name) {
- return ts.createImportSpecifier(propertyName !== undefined && propertyName !== name ? ts.createIdentifier(propertyName) : undefined, ts.createIdentifier(name));
- }
- function makeConst(modifiers, name, init) {
- return ts.createVariableStatement(modifiers, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, /*type*/ undefined, init)], 2 /* Const */));
- }
- function makeExportDeclaration(exportSpecifiers, moduleSpecifier) {
- return ts.createExportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, exportSpecifiers && ts.createNamedExports(exportSpecifiers), moduleSpecifier === undefined ? undefined : ts.createLiteral(moduleSpecifier));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "correctQualifiedNameToIndexedAccessType";
- var errorCodes = [ts.Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var qualifiedName = getQualifiedName(context.sourceFile, context.span.start);
- if (!qualifiedName)
- return undefined;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, qualifiedName); });
- var newText = qualifiedName.left.text + "[\"" + qualifiedName.right.text + "\"]";
- return [codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Rewrite_as_the_indexed_access_type_0, newText], fixId, ts.Diagnostics.Rewrite_all_as_indexed_access_types)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var q = getQualifiedName(diag.file, diag.start);
- if (q) {
- doChange(changes, diag.file, q);
- }
- }); },
- });
- function getQualifiedName(sourceFile, pos) {
- var qualifiedName = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos), ts.isQualifiedName);
- ts.Debug.assert(!!qualifiedName, "Expected position to be owned by a qualified name.");
- return ts.isIdentifier(qualifiedName.left) ? qualifiedName : undefined;
- }
- function doChange(changeTracker, sourceFile, qualifiedName) {
- var rightText = qualifiedName.right.text;
- var replacement = ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined), ts.createLiteralTypeNode(ts.createLiteral(rightText)));
- changeTracker.replaceNode(sourceFile, qualifiedName, replacement);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodes = [ts.Diagnostics.Re_exporting_a_type_when_the_isolatedModules_flag_is_provided_requires_using_export_type.code];
- var fixId = "convertToTypeOnlyExport";
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return fixSingleExportDeclaration(t, getExportSpecifierForDiagnosticSpan(context.span, context.sourceFile), context); });
- if (changes.length) {
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_to_type_only_export, fixId, ts.Diagnostics.Convert_all_re_exported_types_to_type_only_exports)];
- }
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var fixedExportDeclarations = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var exportSpecifier = getExportSpecifierForDiagnosticSpan(diag, context.sourceFile);
- if (exportSpecifier && !ts.addToSeen(fixedExportDeclarations, ts.getNodeId(exportSpecifier.parent.parent))) {
- fixSingleExportDeclaration(changes, exportSpecifier, context);
- }
- });
- }
- });
- function getExportSpecifierForDiagnosticSpan(span, sourceFile) {
- return ts.tryCast(ts.getTokenAtPosition(sourceFile, span.start).parent, ts.isExportSpecifier);
- }
- function fixSingleExportDeclaration(changes, exportSpecifier, context) {
- if (!exportSpecifier) {
- return;
- }
- var exportClause = exportSpecifier.parent;
- var exportDeclaration = exportClause.parent;
- var typeExportSpecifiers = getTypeExportSpecifiers(exportSpecifier, context);
- if (typeExportSpecifiers.length === exportClause.elements.length) {
- changes.replaceNode(context.sourceFile, exportDeclaration, ts.updateExportDeclaration(exportDeclaration, exportDeclaration.decorators, exportDeclaration.modifiers, exportClause, exportDeclaration.moduleSpecifier,
- /*isTypeOnly*/ true));
- }
- else {
- var valueExportDeclaration = ts.updateExportDeclaration(exportDeclaration, exportDeclaration.decorators, exportDeclaration.modifiers, ts.updateNamedExports(exportClause, ts.filter(exportClause.elements, function (e) { return !ts.contains(typeExportSpecifiers, e); })), exportDeclaration.moduleSpecifier,
- /*isTypeOnly*/ false);
- var typeExportDeclaration = ts.createExportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.createNamedExports(typeExportSpecifiers), exportDeclaration.moduleSpecifier,
- /*isTypeOnly*/ true);
- changes.replaceNode(context.sourceFile, exportDeclaration, valueExportDeclaration);
- changes.insertNodeAfter(context.sourceFile, exportDeclaration, typeExportDeclaration);
- }
- }
- function getTypeExportSpecifiers(originExportSpecifier, context) {
- var exportClause = originExportSpecifier.parent;
- if (exportClause.elements.length === 1) {
- return exportClause.elements;
- }
- var diagnostics = ts.getDiagnosticsWithinSpan(ts.createTextSpanFromNode(exportClause), context.program.getSemanticDiagnostics(context.sourceFile, context.cancellationToken));
- return ts.filter(exportClause.elements, function (element) {
- var _a;
- return element === originExportSpecifier || ((_a = ts.findDiagnosticForNode(element, diagnostics)) === null || _a === void 0 ? void 0 : _a.code) === errorCodes[0];
- });
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodes = [ts.Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_the_importsNotUsedAsValues_is_set_to_error.code];
- var fixId = "convertToTypeOnlyImport";
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) {
- var importDeclaration = getImportDeclarationForDiagnosticSpan(context.span, context.sourceFile);
- fixSingleImportDeclaration(t, importDeclaration, context);
- });
- if (changes.length) {
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_to_type_only_import, fixId, ts.Diagnostics.Convert_all_imports_not_used_as_a_value_to_type_only_imports)];
- }
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var importDeclaration = getImportDeclarationForDiagnosticSpan(diag, context.sourceFile);
- fixSingleImportDeclaration(changes, importDeclaration, context);
- });
- }
- });
- function getImportDeclarationForDiagnosticSpan(span, sourceFile) {
- return ts.tryCast(ts.getTokenAtPosition(sourceFile, span.start).parent, ts.isImportDeclaration);
- }
- function fixSingleImportDeclaration(changes, importDeclaration, context) {
- if (!(importDeclaration === null || importDeclaration === void 0 ? void 0 : importDeclaration.importClause)) {
- return;
- }
- var importClause = importDeclaration.importClause;
- // `changes.insertModifierBefore` produces a range that might overlap further changes
- changes.insertText(context.sourceFile, importDeclaration.getStart() + "import".length, " type");
- // `import type foo, { Bar }` is not allowed, so move `foo` to new declaration
- if (importClause.name && importClause.namedBindings) {
- changes.deleteNodeRangeExcludingEnd(context.sourceFile, importClause.name, importDeclaration.importClause.namedBindings);
- changes.insertNodeBefore(context.sourceFile, importDeclaration, ts.updateImportDeclaration(importDeclaration,
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.createImportClause(importClause.name,
- /*namedBindings*/ undefined,
- /*isTypeOnly*/ true), importDeclaration.moduleSpecifier));
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodes = [
- ts.Diagnostics.Class_0_incorrectly_implements_interface_1.code,
- ts.Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code
- ];
- var fixId = "fixClassIncorrectlyImplementsInterface"; // TODO: share a group with fixClassDoesntImplementInheritedAbstractMember?
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var classDeclaration = getClass(sourceFile, span.start);
- return ts.mapDefined(ts.getEffectiveImplementsTypeNodes(classDeclaration), function (implementedTypeNode) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addMissingDeclarations(context, implementedTypeNode, sourceFile, classDeclaration, t, context.preferences); });
- return changes.length === 0 ? undefined : codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Implement_interface_0, implementedTypeNode.getText(sourceFile)], fixId, ts.Diagnostics.Implement_all_unimplemented_interfaces);
- });
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var seenClassDeclarations = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var classDeclaration = getClass(diag.file, diag.start);
- if (ts.addToSeen(seenClassDeclarations, ts.getNodeId(classDeclaration))) {
- for (var _i = 0, _a = ts.getEffectiveImplementsTypeNodes(classDeclaration); _i < _a.length; _i++) {
- var implementedTypeNode = _a[_i];
- addMissingDeclarations(context, implementedTypeNode, diag.file, classDeclaration, changes, context.preferences);
- }
- }
- });
- },
- });
- function getClass(sourceFile, pos) {
- return ts.Debug.checkDefined(ts.getContainingClass(ts.getTokenAtPosition(sourceFile, pos)), "There should be a containing class");
- }
- function symbolPointsToNonPrivateMember(symbol) {
- return !symbol.valueDeclaration || !(ts.getModifierFlags(symbol.valueDeclaration) & 8 /* Private */);
- }
- function addMissingDeclarations(context, implementedTypeNode, sourceFile, classDeclaration, changeTracker, preferences) {
- var checker = context.program.getTypeChecker();
- var maybeHeritageClauseSymbol = getHeritageClauseSymbolTable(classDeclaration, checker);
- // Note that this is ultimately derived from a map indexed by symbol names,
- // so duplicates cannot occur.
- var implementedType = checker.getTypeAtLocation(implementedTypeNode);
- var implementedTypeSymbols = checker.getPropertiesOfType(implementedType);
- var nonPrivateAndNotExistedInHeritageClauseMembers = implementedTypeSymbols.filter(ts.and(symbolPointsToNonPrivateMember, function (symbol) { return !maybeHeritageClauseSymbol.has(symbol.escapedName); }));
- var classType = checker.getTypeAtLocation(classDeclaration);
- var constructor = ts.find(classDeclaration.members, function (m) { return ts.isConstructorDeclaration(m); });
- if (!classType.getNumberIndexType()) {
- createMissingIndexSignatureDeclaration(implementedType, 1 /* Number */);
- }
- if (!classType.getStringIndexType()) {
- createMissingIndexSignatureDeclaration(implementedType, 0 /* String */);
- }
- var importAdder = codefix.createImportAdder(sourceFile, context.program, preferences, context.host);
- codefix.createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, context, preferences, importAdder, function (member) { return insertInterfaceMemberNode(sourceFile, classDeclaration, member); });
- importAdder.writeFixes(changeTracker);
- function createMissingIndexSignatureDeclaration(type, kind) {
- var indexInfoOfKind = checker.getIndexInfoOfType(type, kind);
- if (indexInfoOfKind) {
- insertInterfaceMemberNode(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration, /*flags*/ undefined, codefix.getNoopSymbolTrackerWithResolver(context)));
- }
- }
- // Either adds the node at the top of the class, or if there's a constructor right after that
- function insertInterfaceMemberNode(sourceFile, cls, newElement) {
- if (constructor) {
- changeTracker.insertNodeAfter(sourceFile, constructor, newElement);
- }
- else {
- changeTracker.insertNodeAtClassStart(sourceFile, cls, newElement);
- }
- }
- }
- function getHeritageClauseSymbolTable(classDeclaration, checker) {
- var heritageClauseNode = ts.getEffectiveBaseTypeNode(classDeclaration);
- if (!heritageClauseNode)
- return ts.createSymbolTable();
- var heritageClauseType = checker.getTypeAtLocation(heritageClauseNode);
- var heritageClauseTypeSymbols = checker.getPropertiesOfType(heritageClauseType);
- return ts.createSymbolTable(heritageClauseTypeSymbols.filter(symbolPointsToNonPrivateMember));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- codefix.importFixName = "import";
- var importFixId = "fixMissingImport";
- var errorCodes = [
- ts.Diagnostics.Cannot_find_name_0.code,
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1.code,
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code,
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code,
- ts.Diagnostics.Cannot_find_namespace_0.code,
- ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code,
- ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var errorCode = context.errorCode, preferences = context.preferences, sourceFile = context.sourceFile, span = context.span;
- var info = getFixesInfo(context, errorCode, span.start);
- if (!info)
- return undefined;
- var fixes = info.fixes, symbolName = info.symbolName;
- var quotePreference = ts.getQuotePreference(sourceFile, preferences);
- return fixes.map(function (fix) { return codeActionForFix(context, sourceFile, symbolName, fix, quotePreference); });
- },
- fixIds: [importFixId],
- getAllCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, preferences = context.preferences, host = context.host;
- var importAdder = createImportAdder(sourceFile, program, preferences, host);
- codefix.eachDiagnostic(context, errorCodes, function (diag) { return importAdder.addImportFromDiagnostic(diag, context); });
- return codefix.createCombinedCodeActions(ts.textChanges.ChangeTracker.with(context, importAdder.writeFixes));
- },
- });
- function createImportAdder(sourceFile, program, preferences, host) {
- var compilerOptions = program.getCompilerOptions();
- // Namespace fixes don't conflict, so just build a list.
- var addToNamespace = [];
- var importType = [];
- // Keys are import clause node IDs.
- var addToExisting = ts.createMap();
- var newImports = ts.createMap();
- return { addImportFromDiagnostic: addImportFromDiagnostic, addImportFromExportedSymbol: addImportFromExportedSymbol, writeFixes: writeFixes };
- function addImportFromDiagnostic(diagnostic, context) {
- var info = getFixesInfo(context, diagnostic.code, diagnostic.start);
- if (!info || !info.fixes.length)
- return;
- addImport(info);
- }
- function addImportFromExportedSymbol(exportedSymbol, usageIsTypeOnly) {
- var moduleSymbol = ts.Debug.checkDefined(exportedSymbol.parent);
- var symbolName = ts.getNameForExportedSymbol(exportedSymbol, ts.getEmitScriptTarget(compilerOptions));
- var checker = program.getTypeChecker();
- var symbol = checker.getMergedSymbol(ts.skipAlias(exportedSymbol, checker));
- var exportInfos = getAllReExportingModules(sourceFile, symbol, moduleSymbol, symbolName, sourceFile, compilerOptions, checker, program.getSourceFiles());
- var preferTypeOnlyImport = !!usageIsTypeOnly && compilerOptions.importsNotUsedAsValues === 2 /* Error */;
- var useRequire = shouldUseRequire(sourceFile, compilerOptions);
- var fix = getImportFixForSymbol(sourceFile, exportInfos, moduleSymbol, symbolName, program, /*position*/ undefined, preferTypeOnlyImport, useRequire, host, preferences);
- addImport({ fixes: [fix], symbolName: symbolName });
- }
- function addImport(info) {
- var fixes = info.fixes, symbolName = info.symbolName;
- var fix = ts.first(fixes);
- switch (fix.kind) {
- case 0 /* UseNamespace */:
- addToNamespace.push(fix);
- break;
- case 1 /* ImportType */:
- importType.push(fix);
- break;
- case 2 /* AddToExisting */: {
- var importClauseOrBindingPattern = fix.importClauseOrBindingPattern, importKind = fix.importKind, canUseTypeOnlyImport = fix.canUseTypeOnlyImport;
- var key = String(ts.getNodeId(importClauseOrBindingPattern));
- var entry = addToExisting.get(key);
- if (!entry) {
- addToExisting.set(key, entry = { importClauseOrBindingPattern: importClauseOrBindingPattern, defaultImport: undefined, namedImports: [], canUseTypeOnlyImport: canUseTypeOnlyImport });
- }
- if (importKind === 0 /* Named */) {
- ts.pushIfUnique(entry.namedImports, symbolName);
- }
- else {
- ts.Debug.assert(entry.defaultImport === undefined || entry.defaultImport === symbolName, "(Add to Existing) Default import should be missing or match symbolName");
- entry.defaultImport = symbolName;
- }
- break;
- }
- case 3 /* AddNew */: {
- var moduleSpecifier = fix.moduleSpecifier, importKind = fix.importKind, useRequire = fix.useRequire, typeOnly = fix.typeOnly;
- var entry = newImports.get(moduleSpecifier);
- if (!entry) {
- newImports.set(moduleSpecifier, entry = { namedImports: [], namespaceLikeImport: undefined, typeOnly: typeOnly, useRequire: useRequire });
- }
- else {
- // An import clause can only be type-only if every import fix contributing to it can be type-only.
- entry.typeOnly = entry.typeOnly && typeOnly;
- }
- switch (importKind) {
- case 1 /* Default */:
- ts.Debug.assert(entry.defaultImport === undefined || entry.defaultImport === symbolName, "(Add new) Default import should be missing or match symbolName");
- entry.defaultImport = symbolName;
- break;
- case 0 /* Named */:
- ts.pushIfUnique(entry.namedImports || (entry.namedImports = []), symbolName);
- break;
- case 3 /* CommonJS */:
- case 2 /* Namespace */:
- ts.Debug.assert(entry.namespaceLikeImport === undefined || entry.namespaceLikeImport.name === symbolName, "Namespacelike import shoudl be missing or match symbolName");
- entry.namespaceLikeImport = { importKind: importKind, name: symbolName };
- break;
- }
- break;
- }
- default:
- ts.Debug.assertNever(fix, "fix wasn't never - got kind " + fix.kind);
- }
- }
- function writeFixes(changeTracker) {
- var quotePreference = ts.getQuotePreference(sourceFile, preferences);
- for (var _i = 0, addToNamespace_1 = addToNamespace; _i < addToNamespace_1.length; _i++) {
- var fix = addToNamespace_1[_i];
- addNamespaceQualifier(changeTracker, sourceFile, fix);
- }
- for (var _a = 0, importType_1 = importType; _a < importType_1.length; _a++) {
- var fix = importType_1[_a];
- addImportType(changeTracker, sourceFile, fix, quotePreference);
- }
- addToExisting.forEach(function (_a) {
- var importClauseOrBindingPattern = _a.importClauseOrBindingPattern, defaultImport = _a.defaultImport, namedImports = _a.namedImports, canUseTypeOnlyImport = _a.canUseTypeOnlyImport;
- doAddExistingFix(changeTracker, sourceFile, importClauseOrBindingPattern, defaultImport, namedImports, canUseTypeOnlyImport);
- });
- var newDeclarations;
- newImports.forEach(function (_a, moduleSpecifier) {
- var useRequire = _a.useRequire, imports = __rest(_a, ["useRequire"]);
- var getDeclarations = useRequire ? getNewRequires : getNewImports;
- newDeclarations = ts.combine(newDeclarations, getDeclarations(moduleSpecifier, quotePreference, imports));
- });
- if (newDeclarations) {
- ts.insertImports(changeTracker, sourceFile, newDeclarations, /*blankLineBetween*/ true);
- }
- }
- }
- codefix.createImportAdder = createImportAdder;
- // Sorted with the preferred fix coming first.
- var ImportFixKind;
- (function (ImportFixKind) {
- ImportFixKind[ImportFixKind["UseNamespace"] = 0] = "UseNamespace";
- ImportFixKind[ImportFixKind["ImportType"] = 1] = "ImportType";
- ImportFixKind[ImportFixKind["AddToExisting"] = 2] = "AddToExisting";
- ImportFixKind[ImportFixKind["AddNew"] = 3] = "AddNew";
- })(ImportFixKind || (ImportFixKind = {}));
- var ImportKind;
- (function (ImportKind) {
- ImportKind[ImportKind["Named"] = 0] = "Named";
- ImportKind[ImportKind["Default"] = 1] = "Default";
- ImportKind[ImportKind["Namespace"] = 2] = "Namespace";
- ImportKind[ImportKind["CommonJS"] = 3] = "CommonJS";
- })(ImportKind || (ImportKind = {}));
- function getImportCompletionAction(exportedSymbol, moduleSymbol, sourceFile, symbolName, host, program, formatContext, position, preferences) {
- var compilerOptions = program.getCompilerOptions();
- var exportInfos = getAllReExportingModules(sourceFile, exportedSymbol, moduleSymbol, symbolName, sourceFile, compilerOptions, program.getTypeChecker(), program.getSourceFiles());
- var useRequire = shouldUseRequire(sourceFile, compilerOptions);
- var preferTypeOnlyImport = compilerOptions.importsNotUsedAsValues === 2 /* Error */ && !ts.isSourceFileJS(sourceFile) && ts.isValidTypeOnlyAliasUseSite(ts.getTokenAtPosition(sourceFile, position));
- var moduleSpecifier = ts.first(getNewImportInfos(program, sourceFile, position, preferTypeOnlyImport, useRequire, exportInfos, host, preferences)).moduleSpecifier;
- var fix = getImportFixForSymbol(sourceFile, exportInfos, moduleSymbol, symbolName, program, position, preferTypeOnlyImport, useRequire, host, preferences);
- return { moduleSpecifier: moduleSpecifier, codeAction: codeFixActionToCodeAction(codeActionForFix({ host: host, formatContext: formatContext, preferences: preferences }, sourceFile, symbolName, fix, ts.getQuotePreference(sourceFile, preferences))) };
- }
- codefix.getImportCompletionAction = getImportCompletionAction;
- function getImportFixForSymbol(sourceFile, exportInfos, moduleSymbol, symbolName, program, position, preferTypeOnlyImport, useRequire, host, preferences) {
- ts.Debug.assert(exportInfos.some(function (info) { return info.moduleSymbol === moduleSymbol; }), "Some exportInfo should match the specified moduleSymbol");
- // We sort the best codefixes first, so taking `first` is best.
- return ts.first(getFixForImport(exportInfos, symbolName, position, preferTypeOnlyImport, useRequire, program, sourceFile, host, preferences));
- }
- function codeFixActionToCodeAction(_a) {
- var description = _a.description, changes = _a.changes, commands = _a.commands;
- return { description: description, changes: changes, commands: commands };
- }
- function getAllReExportingModules(importingFile, exportedSymbol, exportingModuleSymbol, symbolName, sourceFile, compilerOptions, checker, allSourceFiles) {
- var result = [];
- forEachExternalModule(checker, allSourceFiles, function (moduleSymbol, moduleFile) {
- // Don't import from a re-export when looking "up" like to `./index` or `../index`.
- if (moduleFile && moduleSymbol !== exportingModuleSymbol && ts.startsWith(sourceFile.fileName, ts.getDirectoryPath(moduleFile.fileName))) {
- return;
- }
- var defaultInfo = getDefaultLikeExportInfo(importingFile, moduleSymbol, checker, compilerOptions);
- if (defaultInfo && defaultInfo.name === symbolName && ts.skipAlias(defaultInfo.symbol, checker) === exportedSymbol) {
- result.push({ moduleSymbol: moduleSymbol, importKind: defaultInfo.kind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(defaultInfo.symbol, checker) });
- }
- for (var _i = 0, _a = checker.getExportsAndPropertiesOfModule(moduleSymbol); _i < _a.length; _i++) {
- var exported = _a[_i];
- if (exported.name === symbolName && ts.skipAlias(exported, checker) === exportedSymbol) {
- result.push({ moduleSymbol: moduleSymbol, importKind: 0 /* Named */, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exported, checker) });
- }
- }
- });
- return result;
- }
- function isTypeOnlySymbol(s, checker) {
- return !(ts.skipAlias(s, checker).flags & 111551 /* Value */);
- }
- function isTypeOnlyPosition(sourceFile, position) {
- return ts.isValidTypeOnlyAliasUseSite(ts.getTokenAtPosition(sourceFile, position));
- }
- function getFixForImport(exportInfos, symbolName,
- /** undefined only for missing JSX namespace */
- position, preferTypeOnlyImport, useRequire, program, sourceFile, host, preferences) {
- var checker = program.getTypeChecker();
- var existingImports = ts.flatMap(exportInfos, function (info) { return getExistingImportDeclarations(info, checker, sourceFile); });
- var useNamespace = position === undefined ? undefined : tryUseExistingNamespaceImport(existingImports, symbolName, position, checker);
- var addToExisting = tryAddToExistingImport(existingImports, position !== undefined && isTypeOnlyPosition(sourceFile, position));
- // Don't bother providing an action to add a new import if we can add to an existing one.
- var addImport = addToExisting ? [addToExisting] : getFixesForAddImport(exportInfos, existingImports, program, sourceFile, position, preferTypeOnlyImport, useRequire, host, preferences);
- return __spreadArrays((useNamespace ? [useNamespace] : ts.emptyArray), addImport);
- }
- function tryUseExistingNamespaceImport(existingImports, symbolName, position, checker) {
- // It is possible that multiple import statements with the same specifier exist in the file.
- // e.g.
- //
- // import * as ns from "foo";
- // import { member1, member2 } from "foo";
- //
- // member3/**/ <-- cusor here
- //
- // in this case we should provie 2 actions:
- // 1. change "member3" to "ns.member3"
- // 2. add "member3" to the second import statement's import list
- // and it is up to the user to decide which one fits best.
- return ts.firstDefined(existingImports, function (_a) {
- var declaration = _a.declaration;
- var namespacePrefix = getNamespaceLikeImportText(declaration);
- if (namespacePrefix) {
- var moduleSymbol = getTargetModuleFromNamespaceLikeImport(declaration, checker);
- if (moduleSymbol && moduleSymbol.exports.has(ts.escapeLeadingUnderscores(symbolName))) {
- return { kind: 0 /* UseNamespace */, namespacePrefix: namespacePrefix, position: position };
- }
- }
- });
- }
- function getTargetModuleFromNamespaceLikeImport(declaration, checker) {
- var _a;
- switch (declaration.kind) {
- case 242 /* VariableDeclaration */:
- return checker.resolveExternalModuleName(declaration.initializer.arguments[0]);
- case 253 /* ImportEqualsDeclaration */:
- return checker.getAliasedSymbol(declaration.symbol);
- case 254 /* ImportDeclaration */:
- var namespaceImport = ts.tryCast((_a = declaration.importClause) === null || _a === void 0 ? void 0 : _a.namedBindings, ts.isNamespaceImport);
- return namespaceImport && checker.getAliasedSymbol(namespaceImport.symbol);
- default:
- return ts.Debug.assertNever(declaration);
- }
- }
- function getNamespaceLikeImportText(declaration) {
- var _a, _b, _c;
- switch (declaration.kind) {
- case 242 /* VariableDeclaration */:
- return (_a = ts.tryCast(declaration.name, ts.isIdentifier)) === null || _a === void 0 ? void 0 : _a.text;
- case 253 /* ImportEqualsDeclaration */:
- return declaration.name.text;
- case 254 /* ImportDeclaration */:
- return (_c = ts.tryCast((_b = declaration.importClause) === null || _b === void 0 ? void 0 : _b.namedBindings, ts.isNamespaceImport)) === null || _c === void 0 ? void 0 : _c.name.text;
- default:
- return ts.Debug.assertNever(declaration);
- }
- }
- function tryAddToExistingImport(existingImports, canUseTypeOnlyImport) {
- return ts.firstDefined(existingImports, function (_a) {
- var declaration = _a.declaration, importKind = _a.importKind;
- if (declaration.kind === 253 /* ImportEqualsDeclaration */)
- return undefined;
- if (declaration.kind === 242 /* VariableDeclaration */) {
- return (importKind === 0 /* Named */ || importKind === 1 /* Default */) && declaration.name.kind === 189 /* ObjectBindingPattern */
- ? { kind: 2 /* AddToExisting */, importClauseOrBindingPattern: declaration.name, importKind: importKind, moduleSpecifier: declaration.initializer.arguments[0].text, canUseTypeOnlyImport: false }
- : undefined;
- }
- var importClause = declaration.importClause;
- if (!importClause)
- return undefined;
- var name = importClause.name, namedBindings = importClause.namedBindings;
- return importKind === 1 /* Default */ && !name || importKind === 0 /* Named */ && (!namedBindings || namedBindings.kind === 257 /* NamedImports */)
- ? { kind: 2 /* AddToExisting */, importClauseOrBindingPattern: importClause, importKind: importKind, moduleSpecifier: declaration.moduleSpecifier.getText(), canUseTypeOnlyImport: canUseTypeOnlyImport }
- : undefined;
- });
- }
- function getExistingImportDeclarations(_a, checker, sourceFile) {
- var moduleSymbol = _a.moduleSymbol, importKind = _a.importKind, exportedSymbolIsTypeOnly = _a.exportedSymbolIsTypeOnly;
- // Can't use an es6 import for a type in JS.
- return exportedSymbolIsTypeOnly && ts.isSourceFileJS(sourceFile) ? ts.emptyArray : ts.mapDefined(sourceFile.imports, function (moduleSpecifier) {
- var i = ts.importFromModuleSpecifier(moduleSpecifier);
- if (ts.isRequireVariableDeclaration(i.parent, /*requireStringLiteralLikeArgument*/ true)) {
- return checker.resolveExternalModuleName(moduleSpecifier) === moduleSymbol ? { declaration: i.parent, importKind: importKind } : undefined;
- }
- if (i.kind === 254 /* ImportDeclaration */ || i.kind === 253 /* ImportEqualsDeclaration */) {
- return checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind: importKind } : undefined;
- }
- });
- }
- function shouldUseRequire(sourceFile, compilerOptions) {
- return ts.isSourceFileJS(sourceFile)
- && !sourceFile.externalModuleIndicator
- && (!!sourceFile.commonJsModuleIndicator || ts.getEmitModuleKind(compilerOptions) < ts.ModuleKind.ES2015);
- }
- function getNewImportInfos(program, sourceFile, position, preferTypeOnlyImport, useRequire, moduleSymbols, host, preferences) {
- var isJs = ts.isSourceFileJS(sourceFile);
- var compilerOptions = program.getCompilerOptions();
- var allowsImportingSpecifier = createAutoImportFilter(sourceFile, program, host).allowsImportingSpecifier;
- var choicesForEachExportingModule = ts.flatMap(moduleSymbols, function (_a) {
- var moduleSymbol = _a.moduleSymbol, importKind = _a.importKind, exportedSymbolIsTypeOnly = _a.exportedSymbolIsTypeOnly;
- return ts.moduleSpecifiers.getModuleSpecifiers(moduleSymbol, compilerOptions, sourceFile, ts.createModuleSpecifierResolutionHost(program, host), preferences)
- .map(function (moduleSpecifier) {
- // `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types.
- return exportedSymbolIsTypeOnly && isJs
- ? { kind: 1 /* ImportType */, moduleSpecifier: moduleSpecifier, position: ts.Debug.checkDefined(position, "position should be defined") }
- : { kind: 3 /* AddNew */, moduleSpecifier: moduleSpecifier, importKind: importKind, useRequire: useRequire, typeOnly: preferTypeOnlyImport };
- });
- });
- // Sort by presence in package.json, then shortest paths first
- return ts.sort(choicesForEachExportingModule, function (a, b) {
- var allowsImportingA = allowsImportingSpecifier(a.moduleSpecifier);
- var allowsImportingB = allowsImportingSpecifier(b.moduleSpecifier);
- if (allowsImportingA && !allowsImportingB) {
- return -1;
- }
- if (allowsImportingB && !allowsImportingA) {
- return 1;
- }
- return a.moduleSpecifier.length - b.moduleSpecifier.length;
- });
- }
- function getFixesForAddImport(exportInfos, existingImports, program, sourceFile, position, preferTypeOnlyImport, useRequire, host, preferences) {
- var existingDeclaration = ts.firstDefined(existingImports, function (info) { return newImportInfoFromExistingSpecifier(info, preferTypeOnlyImport, useRequire); });
- return existingDeclaration ? [existingDeclaration] : getNewImportInfos(program, sourceFile, position, preferTypeOnlyImport, useRequire, exportInfos, host, preferences);
- }
- function newImportInfoFromExistingSpecifier(_a, preferTypeOnlyImport, useRequire) {
- var declaration = _a.declaration, importKind = _a.importKind;
- var moduleSpecifier = declaration.kind === 254 /* ImportDeclaration */ ? declaration.moduleSpecifier :
- declaration.kind === 242 /* VariableDeclaration */ ? declaration.initializer.arguments[0] :
- declaration.moduleReference.kind === 265 /* ExternalModuleReference */ ? declaration.moduleReference.expression :
- undefined;
- return moduleSpecifier && ts.isStringLiteral(moduleSpecifier)
- ? { kind: 3 /* AddNew */, moduleSpecifier: moduleSpecifier.text, importKind: importKind, typeOnly: preferTypeOnlyImport, useRequire: useRequire }
- : undefined;
- }
- function getFixesInfo(context, errorCode, pos) {
- var symbolToken = ts.getTokenAtPosition(context.sourceFile, pos);
- var info = errorCode === ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code
- ? getFixesInfoForUMDImport(context, symbolToken)
- : ts.isIdentifier(symbolToken) ? getFixesInfoForNonUMDImport(context, symbolToken) : undefined;
- return info && __assign(__assign({}, info), { fixes: ts.sort(info.fixes, function (a, b) { return a.kind - b.kind; }) });
- }
- function getFixesInfoForUMDImport(_a, token) {
- var sourceFile = _a.sourceFile, program = _a.program, host = _a.host, preferences = _a.preferences;
- var checker = program.getTypeChecker();
- var umdSymbol = getUmdSymbol(token, checker);
- if (!umdSymbol)
- return undefined;
- var symbol = checker.getAliasedSymbol(umdSymbol);
- var symbolName = umdSymbol.name;
- var exportInfos = [{ moduleSymbol: symbol, importKind: getUmdImportKind(sourceFile, program.getCompilerOptions()), exportedSymbolIsTypeOnly: false }];
- var useRequire = shouldUseRequire(sourceFile, program.getCompilerOptions());
- var fixes = getFixForImport(exportInfos, symbolName, ts.isIdentifier(token) ? token.getStart(sourceFile) : undefined, /*preferTypeOnlyImport*/ false, useRequire, program, sourceFile, host, preferences);
- return { fixes: fixes, symbolName: symbolName };
- }
- function getUmdSymbol(token, checker) {
- // try the identifier to see if it is the umd symbol
- var umdSymbol = ts.isIdentifier(token) ? checker.getSymbolAtLocation(token) : undefined;
- if (ts.isUMDExportSymbol(umdSymbol))
- return umdSymbol;
- // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`.
- var parent = token.parent;
- return (ts.isJsxOpeningLikeElement(parent) && parent.tagName === token) || ts.isJsxOpeningFragment(parent)
- ? ts.tryCast(checker.resolveName(checker.getJsxNamespace(parent), ts.isJsxOpeningLikeElement(parent) ? token : parent, 111551 /* Value */, /*excludeGlobals*/ false), ts.isUMDExportSymbol)
- : undefined;
- }
- function getUmdImportKind(importingFile, compilerOptions) {
- // Import a synthetic `default` if enabled.
- if (ts.getAllowSyntheticDefaultImports(compilerOptions)) {
- return 1 /* Default */;
- }
- // When a synthetic `default` is unavailable, use `import..require` if the module kind supports it.
- var moduleKind = ts.getEmitModuleKind(compilerOptions);
- switch (moduleKind) {
- case ts.ModuleKind.AMD:
- case ts.ModuleKind.CommonJS:
- case ts.ModuleKind.UMD:
- if (ts.isInJSFile(importingFile)) {
- return ts.isExternalModule(importingFile) ? 2 /* Namespace */ : 3 /* CommonJS */;
- }
- return 3 /* CommonJS */;
- case ts.ModuleKind.System:
- case ts.ModuleKind.ES2015:
- case ts.ModuleKind.ES2020:
- case ts.ModuleKind.ESNext:
- case ts.ModuleKind.None:
- // Fall back to the `import * as ns` style import.
- return 2 /* Namespace */;
- default:
- return ts.Debug.assertNever(moduleKind, "Unexpected moduleKind " + moduleKind);
- }
- }
- function getFixesInfoForNonUMDImport(_a, symbolToken) {
- var sourceFile = _a.sourceFile, program = _a.program, cancellationToken = _a.cancellationToken, host = _a.host, preferences = _a.preferences;
- var checker = program.getTypeChecker();
- // If we're at ``, we must check if `Foo` is already in scope, and if so, get an import for `React` instead.
- var symbolName = ts.isJsxOpeningLikeElement(symbolToken.parent)
- && symbolToken.parent.tagName === symbolToken
- && (ts.isIntrinsicJsxName(symbolToken.text) || checker.resolveName(symbolToken.text, symbolToken, 67108863 /* All */, /*excludeGlobals*/ false))
- ? checker.getJsxNamespace(sourceFile)
- : symbolToken.text;
- // "default" is a keyword and not a legal identifier for the import, so we don't expect it here
- ts.Debug.assert(symbolName !== "default" /* Default */, "'default' isn't a legal identifier and couldn't occur here");
- var compilerOptions = program.getCompilerOptions();
- var preferTypeOnlyImport = compilerOptions.importsNotUsedAsValues === 2 /* Error */ && ts.isValidTypeOnlyAliasUseSite(symbolToken);
- var useRequire = shouldUseRequire(sourceFile, compilerOptions);
- var exportInfos = getExportInfos(symbolName, ts.getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, checker, program, host);
- var fixes = ts.arrayFrom(ts.flatMapIterator(exportInfos.entries(), function (_a) {
- var _ = _a[0], exportInfos = _a[1];
- return getFixForImport(exportInfos, symbolName, symbolToken.getStart(sourceFile), preferTypeOnlyImport, useRequire, program, sourceFile, host, preferences);
- }));
- return { fixes: fixes, symbolName: symbolName };
- }
- // Returns a map from an exported symbol's ID to a list of every way it's (re-)exported.
- function getExportInfos(symbolName, currentTokenMeaning, cancellationToken, sourceFile, checker, program, host) {
- // For each original symbol, keep all re-exports of that symbol together so we can call `getCodeActionsForImport` on the whole group at once.
- // Maps symbol id to info for modules providing that symbol (original export + re-exports).
- var originalSymbolToExportInfos = ts.createMultiMap();
- function addSymbol(moduleSymbol, exportedSymbol, importKind) {
- originalSymbolToExportInfos.add(ts.getUniqueSymbolId(exportedSymbol, checker).toString(), { moduleSymbol: moduleSymbol, importKind: importKind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(exportedSymbol, checker) });
- }
- forEachExternalModuleToImportFrom(program, host, sourceFile, /*filterByPackageJson*/ true, function (moduleSymbol) {
- cancellationToken.throwIfCancellationRequested();
- var defaultInfo = getDefaultLikeExportInfo(sourceFile, moduleSymbol, checker, program.getCompilerOptions());
- if (defaultInfo && defaultInfo.name === symbolName && symbolHasMeaning(defaultInfo.symbolForMeaning, currentTokenMeaning)) {
- addSymbol(moduleSymbol, defaultInfo.symbol, defaultInfo.kind);
- }
- // check exports with the same name
- var exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol);
- if (exportSymbolWithIdenticalName && symbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) {
- addSymbol(moduleSymbol, exportSymbolWithIdenticalName, 0 /* Named */);
- }
- });
- return originalSymbolToExportInfos;
- }
- function getDefaultLikeExportInfo(importingFile, moduleSymbol, checker, compilerOptions) {
- var exported = getDefaultLikeExportWorker(importingFile, moduleSymbol, checker, compilerOptions);
- if (!exported)
- return undefined;
- var symbol = exported.symbol, kind = exported.kind;
- var info = getDefaultExportInfoWorker(symbol, moduleSymbol, checker, compilerOptions);
- return info && __assign({ symbol: symbol, kind: kind }, info);
- }
- function getDefaultLikeExportWorker(importingFile, moduleSymbol, checker, compilerOptions) {
- var defaultExport = checker.tryGetMemberInModuleExports("default" /* Default */, moduleSymbol);
- if (defaultExport)
- return { symbol: defaultExport, kind: 1 /* Default */ };
- var exportEquals = checker.resolveExternalModuleSymbol(moduleSymbol);
- return exportEquals === moduleSymbol ? undefined : { symbol: exportEquals, kind: getExportEqualsImportKind(importingFile, compilerOptions) };
- }
- function getExportEqualsImportKind(importingFile, compilerOptions) {
- var allowSyntheticDefaults = ts.getAllowSyntheticDefaultImports(compilerOptions);
- // 1. 'import =' will not work in es2015+, so the decision is between a default
- // and a namespace import, based on allowSyntheticDefaultImports/esModuleInterop.
- if (ts.getEmitModuleKind(compilerOptions) >= ts.ModuleKind.ES2015) {
- return allowSyntheticDefaults ? 1 /* Default */ : 2 /* Namespace */;
- }
- // 2. 'import =' will not work in JavaScript, so the decision is between a default
- // and const/require.
- if (ts.isInJSFile(importingFile)) {
- return ts.isExternalModule(importingFile) ? 1 /* Default */ : 3 /* CommonJS */;
- }
- // 3. At this point the most correct choice is probably 'import =', but people
- // really hate that, so look to see if the importing file has any precedent
- // on how to handle it.
- for (var _i = 0, _a = importingFile.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- if (ts.isImportEqualsDeclaration(statement)) {
- return 3 /* CommonJS */;
- }
- }
- // 4. We have no precedent to go on, so just use a default import if
- // allowSyntheticDefaultImports/esModuleInterop is enabled.
- return allowSyntheticDefaults ? 1 /* Default */ : 3 /* CommonJS */;
- }
- function getDefaultExportInfoWorker(defaultExport, moduleSymbol, checker, compilerOptions) {
- var localSymbol = ts.getLocalSymbolForExportDefault(defaultExport);
- if (localSymbol)
- return { symbolForMeaning: localSymbol, name: localSymbol.name };
- var name = getNameForExportDefault(defaultExport);
- if (name !== undefined)
- return { symbolForMeaning: defaultExport, name: name };
- if (defaultExport.flags & 2097152 /* Alias */) {
- var aliased = checker.getImmediateAliasedSymbol(defaultExport);
- return aliased && getDefaultExportInfoWorker(aliased, ts.Debug.checkDefined(aliased.parent, "Alias targets of default exports must have a parent"), checker, compilerOptions);
- }
- if (defaultExport.escapedName !== "default" /* Default */ &&
- defaultExport.escapedName !== "export=" /* ExportEquals */) {
- return { symbolForMeaning: defaultExport, name: defaultExport.getName() };
- }
- return { symbolForMeaning: defaultExport, name: moduleSymbolToValidIdentifier(moduleSymbol, compilerOptions.target) };
- }
- function getNameForExportDefault(symbol) {
- return symbol.declarations && ts.firstDefined(symbol.declarations, function (declaration) {
- if (ts.isExportAssignment(declaration)) {
- if (ts.isIdentifier(declaration.expression)) {
- return declaration.expression.text;
- }
- }
- else if (ts.isExportSpecifier(declaration)) {
- ts.Debug.assert(declaration.name.text === "default" /* Default */, "Expected the specifier to be a default export");
- return declaration.propertyName && declaration.propertyName.text;
- }
- });
- }
- function codeActionForFix(context, sourceFile, symbolName, fix, quotePreference) {
- var diag;
- var changes = ts.textChanges.ChangeTracker.with(context, function (tracker) {
- diag = codeActionForFixWorker(tracker, sourceFile, symbolName, fix, quotePreference);
- });
- return codefix.createCodeFixAction(codefix.importFixName, changes, diag, importFixId, ts.Diagnostics.Add_all_missing_imports);
- }
- function codeActionForFixWorker(changes, sourceFile, symbolName, fix, quotePreference) {
- switch (fix.kind) {
- case 0 /* UseNamespace */:
- addNamespaceQualifier(changes, sourceFile, fix);
- return [ts.Diagnostics.Change_0_to_1, symbolName, fix.namespacePrefix + "." + symbolName];
- case 1 /* ImportType */:
- addImportType(changes, sourceFile, fix, quotePreference);
- return [ts.Diagnostics.Change_0_to_1, symbolName, getImportTypePrefix(fix.moduleSpecifier, quotePreference) + symbolName];
- case 2 /* AddToExisting */: {
- var importClauseOrBindingPattern = fix.importClauseOrBindingPattern, importKind = fix.importKind, canUseTypeOnlyImport = fix.canUseTypeOnlyImport, moduleSpecifier = fix.moduleSpecifier;
- doAddExistingFix(changes, sourceFile, importClauseOrBindingPattern, importKind === 1 /* Default */ ? symbolName : undefined, importKind === 0 /* Named */ ? [symbolName] : ts.emptyArray, canUseTypeOnlyImport);
- var moduleSpecifierWithoutQuotes = ts.stripQuotes(moduleSpecifier);
- return [importKind === 1 /* Default */ ? ts.Diagnostics.Add_default_import_0_to_existing_import_declaration_from_1 : ts.Diagnostics.Add_0_to_existing_import_declaration_from_1, symbolName, moduleSpecifierWithoutQuotes]; // you too!
- }
- case 3 /* AddNew */: {
- var importKind = fix.importKind, moduleSpecifier = fix.moduleSpecifier, typeOnly = fix.typeOnly, useRequire = fix.useRequire;
- var getDeclarations = useRequire ? getNewRequires : getNewImports;
- var importsCollection = importKind === 1 /* Default */ ? { defaultImport: symbolName, typeOnly: typeOnly } :
- importKind === 0 /* Named */ ? { namedImports: [symbolName], typeOnly: typeOnly } :
- { namespaceLikeImport: { importKind: importKind, name: symbolName }, typeOnly: typeOnly };
- ts.insertImports(changes, sourceFile, getDeclarations(moduleSpecifier, quotePreference, importsCollection), /*blankLineBetween*/ true);
- return [importKind === 1 /* Default */ ? ts.Diagnostics.Import_default_0_from_module_1 : ts.Diagnostics.Import_0_from_module_1, symbolName, moduleSpecifier];
- }
- default:
- return ts.Debug.assertNever(fix, "Unexpected fix kind " + fix.kind);
- }
- }
- function doAddExistingFix(changes, sourceFile, clause, defaultImport, namedImports, canUseTypeOnlyImport) {
- if (clause.kind === 189 /* ObjectBindingPattern */) {
- if (defaultImport) {
- addElementToBindingPattern(clause, defaultImport, "default");
- }
- for (var _i = 0, namedImports_1 = namedImports; _i < namedImports_1.length; _i++) {
- var specifier = namedImports_1[_i];
- addElementToBindingPattern(clause, specifier, /*propertyName*/ undefined);
- }
- return;
- }
- var convertTypeOnlyToRegular = !canUseTypeOnlyImport && clause.isTypeOnly;
- if (defaultImport) {
- ts.Debug.assert(!clause.name, "Cannot add a default import to an import clause that already has one");
- changes.insertNodeAt(sourceFile, clause.getStart(sourceFile), ts.createIdentifier(defaultImport), { suffix: ", " });
- }
- if (namedImports.length) {
- var specifiers = namedImports.map(function (name) { return ts.createImportSpecifier(/*propertyName*/ undefined, ts.createIdentifier(name)); });
- if (clause.namedBindings && ts.cast(clause.namedBindings, ts.isNamedImports).elements.length) {
- for (var _a = 0, specifiers_1 = specifiers; _a < specifiers_1.length; _a++) {
- var spec = specifiers_1[_a];
- changes.insertNodeInListAfter(sourceFile, ts.last(ts.cast(clause.namedBindings, ts.isNamedImports).elements), spec);
- }
- }
- else {
- if (specifiers.length) {
- var namedImports_2 = ts.createNamedImports(specifiers);
- if (clause.namedBindings) {
- changes.replaceNode(sourceFile, clause.namedBindings, namedImports_2);
- }
- else {
- changes.insertNodeAfter(sourceFile, ts.Debug.checkDefined(clause.name, "Import clause must have either named imports or a default import"), namedImports_2);
- }
- }
- }
- }
- if (convertTypeOnlyToRegular) {
- changes.delete(sourceFile, ts.getTypeKeywordOfTypeOnlyImport(clause, sourceFile));
- }
- function addElementToBindingPattern(bindingPattern, name, propertyName) {
- var element = ts.createBindingElement(/*dotDotDotToken*/ undefined, propertyName, name);
- if (bindingPattern.elements.length) {
- changes.insertNodeInListAfter(sourceFile, ts.last(bindingPattern.elements), element);
- }
- else {
- changes.replaceNode(sourceFile, bindingPattern, ts.createObjectBindingPattern([element]));
- }
- }
- }
- function addNamespaceQualifier(changes, sourceFile, _a) {
- var namespacePrefix = _a.namespacePrefix, position = _a.position;
- changes.insertText(sourceFile, position, namespacePrefix + ".");
- }
- function addImportType(changes, sourceFile, _a, quotePreference) {
- var moduleSpecifier = _a.moduleSpecifier, position = _a.position;
- changes.insertText(sourceFile, position, getImportTypePrefix(moduleSpecifier, quotePreference));
- }
- function getImportTypePrefix(moduleSpecifier, quotePreference) {
- var quote = ts.getQuoteFromPreference(quotePreference);
- return "import(" + quote + moduleSpecifier + quote + ").";
- }
- function getNewImports(moduleSpecifier, quotePreference, imports) {
- var _a, _b;
- var quotedModuleSpecifier = ts.makeStringLiteral(moduleSpecifier, quotePreference);
- var statements;
- if (imports.defaultImport !== undefined || ((_a = imports.namedImports) === null || _a === void 0 ? void 0 : _a.length)) {
- statements = ts.combine(statements, ts.makeImport(imports.defaultImport === undefined ? undefined : ts.createIdentifier(imports.defaultImport), (_b = imports.namedImports) === null || _b === void 0 ? void 0 : _b.map(function (n) { return ts.createImportSpecifier(/*propertyName*/ undefined, ts.createIdentifier(n)); }), moduleSpecifier, quotePreference, imports.typeOnly));
- }
- var namespaceLikeImport = imports.namespaceLikeImport, typeOnly = imports.typeOnly;
- if (namespaceLikeImport) {
- var declaration = namespaceLikeImport.importKind === 3 /* CommonJS */
- ? ts.createImportEqualsDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.createIdentifier(namespaceLikeImport.name), ts.createExternalModuleReference(quotedModuleSpecifier))
- : ts.createImportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.createImportClause(
- /*name*/ undefined, ts.createNamespaceImport(ts.createIdentifier(namespaceLikeImport.name)), typeOnly), quotedModuleSpecifier);
- statements = ts.combine(statements, declaration);
- }
- return ts.Debug.checkDefined(statements);
- }
- function getNewRequires(moduleSpecifier, quotePreference, imports) {
- var _a, _b;
- var quotedModuleSpecifier = ts.makeStringLiteral(moduleSpecifier, quotePreference);
- var statements;
- // const { default: foo, bar, etc } = require('./mod');
- if (imports.defaultImport || ((_a = imports.namedImports) === null || _a === void 0 ? void 0 : _a.length)) {
- var bindingElements = ((_b = imports.namedImports) === null || _b === void 0 ? void 0 : _b.map(function (name) { return ts.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name); })) || [];
- if (imports.defaultImport) {
- bindingElements.unshift(ts.createBindingElement(/*dotDotDotToken*/ undefined, "default", imports.defaultImport));
- }
- var declaration = createConstEqualsRequireDeclaration(ts.createObjectBindingPattern(bindingElements), quotedModuleSpecifier);
- statements = ts.combine(statements, declaration);
- }
- // const foo = require('./mod');
- if (imports.namespaceLikeImport) {
- var declaration = createConstEqualsRequireDeclaration(imports.namespaceLikeImport.name, quotedModuleSpecifier);
- statements = ts.combine(statements, declaration);
- }
- return ts.Debug.checkDefined(statements);
- }
- function createConstEqualsRequireDeclaration(name, quotedModuleSpecifier) {
- return ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([
- ts.createVariableDeclaration(typeof name === "string" ? ts.createIdentifier(name) : name,
- /*type*/ undefined, ts.createCall(ts.createIdentifier("require"), /*typeArguments*/ undefined, [quotedModuleSpecifier]))
- ], 2 /* Const */));
- }
- function symbolHasMeaning(_a, meaning) {
- var declarations = _a.declarations;
- return ts.some(declarations, function (decl) { return !!(ts.getMeaningFromDeclaration(decl) & meaning); });
- }
- function forEachExternalModuleToImportFrom(program, host, from, filterByPackageJson, cb) {
- var filteredCount = 0;
- var moduleSpecifierResolutionHost = ts.createModuleSpecifierResolutionHost(program, host);
- var packageJson = filterByPackageJson && createAutoImportFilter(from, program, host, moduleSpecifierResolutionHost);
- forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), function (module, sourceFile) {
- if (sourceFile === undefined) {
- if (!packageJson || packageJson.allowsImportingAmbientModule(module)) {
- cb(module);
- }
- else if (packageJson) {
- filteredCount++;
- }
- }
- else if (sourceFile &&
- sourceFile !== from &&
- isImportableFile(program, from, sourceFile, moduleSpecifierResolutionHost)) {
- if (!packageJson || packageJson.allowsImportingSourceFile(sourceFile)) {
- cb(module);
- }
- else if (packageJson) {
- filteredCount++;
- }
- }
- });
- if (host.log) {
- host.log("forEachExternalModuleToImportFrom: filtered out " + filteredCount + " modules by package.json contents");
- }
- }
- codefix.forEachExternalModuleToImportFrom = forEachExternalModuleToImportFrom;
- function forEachExternalModule(checker, allSourceFiles, cb) {
- for (var _i = 0, _a = checker.getAmbientModules(); _i < _a.length; _i++) {
- var ambient = _a[_i];
- cb(ambient, /*sourceFile*/ undefined);
- }
- for (var _b = 0, allSourceFiles_1 = allSourceFiles; _b < allSourceFiles_1.length; _b++) {
- var sourceFile = allSourceFiles_1[_b];
- if (ts.isExternalOrCommonJsModule(sourceFile)) {
- cb(checker.getMergedSymbol(sourceFile.symbol), sourceFile);
- }
- }
- }
- function isImportableFile(program, from, to, moduleSpecifierResolutionHost) {
- var _a;
- var getCanonicalFileName = ts.hostGetCanonicalFileName(moduleSpecifierResolutionHost);
- var globalTypingsCache = (_a = moduleSpecifierResolutionHost.getGlobalTypingsCacheLocation) === null || _a === void 0 ? void 0 : _a.call(moduleSpecifierResolutionHost);
- return !!ts.moduleSpecifiers.forEachFileNameOfModule(from.fileName, to.fileName, moduleSpecifierResolutionHost,
- /*preferSymlinks*/ false, function (toPath) {
- var toFile = program.getSourceFile(toPath);
- // Determine to import using toPath only if toPath is what we were looking at
- // or there doesnt exist the file in the program by the symlink
- return (toFile === to || !toFile) &&
- isImportablePath(from.fileName, toPath, getCanonicalFileName, globalTypingsCache);
- });
- }
- /**
- * Don't include something from a `node_modules` that isn't actually reachable by a global import.
- * A relative import to node_modules is usually a bad idea.
- */
- function isImportablePath(fromPath, toPath, getCanonicalFileName, globalCachePath) {
- // If it's in a `node_modules` but is not reachable from here via a global import, don't bother.
- var toNodeModules = ts.forEachAncestorDirectory(toPath, function (ancestor) { return ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined; });
- var toNodeModulesParent = toNodeModules && ts.getDirectoryPath(getCanonicalFileName(toNodeModules));
- return toNodeModulesParent === undefined
- || ts.startsWith(getCanonicalFileName(fromPath), toNodeModulesParent)
- || (!!globalCachePath && ts.startsWith(getCanonicalFileName(globalCachePath), toNodeModulesParent));
- }
- function moduleSymbolToValidIdentifier(moduleSymbol, target) {
- return moduleSpecifierToValidIdentifier(ts.removeFileExtension(ts.stripQuotes(moduleSymbol.name)), target);
- }
- codefix.moduleSymbolToValidIdentifier = moduleSymbolToValidIdentifier;
- function moduleSpecifierToValidIdentifier(moduleSpecifier, target) {
- var baseName = ts.getBaseFileName(ts.removeSuffix(moduleSpecifier, "/index"));
- var res = "";
- var lastCharWasValid = true;
- var firstCharCode = baseName.charCodeAt(0);
- if (ts.isIdentifierStart(firstCharCode, target)) {
- res += String.fromCharCode(firstCharCode);
- }
- else {
- lastCharWasValid = false;
- }
- for (var i = 1; i < baseName.length; i++) {
- var ch = baseName.charCodeAt(i);
- var isValid = ts.isIdentifierPart(ch, target);
- if (isValid) {
- var char = String.fromCharCode(ch);
- if (!lastCharWasValid) {
- char = char.toUpperCase();
- }
- res += char;
- }
- lastCharWasValid = isValid;
- }
- // Need `|| "_"` to ensure result isn't empty.
- return !ts.isStringANonContextualKeyword(res) ? res || "_" : "_" + res;
- }
- codefix.moduleSpecifierToValidIdentifier = moduleSpecifierToValidIdentifier;
- function createAutoImportFilter(fromFile, program, host, moduleSpecifierResolutionHost) {
- if (moduleSpecifierResolutionHost === void 0) { moduleSpecifierResolutionHost = ts.createModuleSpecifierResolutionHost(program, host); }
- var packageJsons = host.getPackageJsonsVisibleToFile && host.getPackageJsonsVisibleToFile(fromFile.fileName) || ts.getPackageJsonsVisibleToFile(fromFile.fileName, host);
- var dependencyGroups = 1 /* Dependencies */ | 2 /* DevDependencies */ | 8 /* OptionalDependencies */;
- var usesNodeCoreModules;
- return { allowsImportingAmbientModule: allowsImportingAmbientModule, allowsImportingSourceFile: allowsImportingSourceFile, allowsImportingSpecifier: allowsImportingSpecifier, moduleSpecifierResolutionHost: moduleSpecifierResolutionHost };
- function moduleSpecifierIsCoveredByPackageJson(specifier) {
- var packageName = getNodeModuleRootSpecifier(specifier);
- for (var _i = 0, packageJsons_1 = packageJsons; _i < packageJsons_1.length; _i++) {
- var packageJson = packageJsons_1[_i];
- if (packageJson.has(packageName, dependencyGroups) || packageJson.has(ts.getTypesPackageName(packageName), dependencyGroups)) {
- return true;
- }
- }
- return false;
- }
- function allowsImportingAmbientModule(moduleSymbol) {
- if (!packageJsons.length) {
- return true;
- }
- var declaringSourceFile = moduleSymbol.valueDeclaration.getSourceFile();
- var declaringNodeModuleName = getNodeModulesPackageNameFromFileName(declaringSourceFile.fileName);
- if (typeof declaringNodeModuleName === "undefined") {
- return true;
- }
- var declaredModuleSpecifier = ts.stripQuotes(moduleSymbol.getName());
- if (isAllowedCoreNodeModulesImport(declaredModuleSpecifier)) {
- return true;
- }
- return moduleSpecifierIsCoveredByPackageJson(declaringNodeModuleName)
- || moduleSpecifierIsCoveredByPackageJson(declaredModuleSpecifier);
- }
- function allowsImportingSourceFile(sourceFile) {
- if (!packageJsons.length) {
- return true;
- }
- var moduleSpecifier = getNodeModulesPackageNameFromFileName(sourceFile.fileName);
- if (!moduleSpecifier) {
- return true;
- }
- return moduleSpecifierIsCoveredByPackageJson(moduleSpecifier);
- }
- /**
- * Use for a specific module specifier that has already been resolved.
- * Use `allowsImportingAmbientModule` or `allowsImportingSourceFile` to resolve
- * the best module specifier for a given module _and_ determine if it’s importable.
- */
- function allowsImportingSpecifier(moduleSpecifier) {
- if (!packageJsons.length || isAllowedCoreNodeModulesImport(moduleSpecifier)) {
- return true;
- }
- if (ts.pathIsRelative(moduleSpecifier) || ts.isRootedDiskPath(moduleSpecifier)) {
- return true;
- }
- return moduleSpecifierIsCoveredByPackageJson(moduleSpecifier);
- }
- function isAllowedCoreNodeModulesImport(moduleSpecifier) {
- // If we’re in JavaScript, it can be difficult to tell whether the user wants to import
- // from Node core modules or not. We can start by seeing if the user is actually using
- // any node core modules, as opposed to simply having @types/node accidentally as a
- // dependency of a dependency.
- if (ts.isSourceFileJS(fromFile) && ts.JsTyping.nodeCoreModules.has(moduleSpecifier)) {
- if (usesNodeCoreModules === undefined) {
- usesNodeCoreModules = ts.consumesNodeCoreModules(fromFile);
- }
- if (usesNodeCoreModules) {
- return true;
- }
- }
- return false;
- }
- function getNodeModulesPackageNameFromFileName(importedFileName) {
- if (!ts.stringContains(importedFileName, "node_modules")) {
- return undefined;
- }
- var specifier = ts.moduleSpecifiers.getNodeModulesPackageName(host.getCompilationSettings(), fromFile.path, importedFileName, moduleSpecifierResolutionHost);
- if (!specifier) {
- return undefined;
- }
- // Paths here are not node_modules, so we don’t care about them;
- // returning anything will trigger a lookup in package.json.
- if (!ts.pathIsRelative(specifier) && !ts.isRootedDiskPath(specifier)) {
- return getNodeModuleRootSpecifier(specifier);
- }
- }
- function getNodeModuleRootSpecifier(fullSpecifier) {
- var components = ts.getPathComponents(ts.getPackageNameFromTypesPackageName(fullSpecifier)).slice(1);
- // Scoped packages
- if (ts.startsWith(components[0], "@")) {
- return components[0] + "/" + components[1];
- }
- return components[0];
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixImplicitThis";
- var errorCodes = [ts.Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, span = context.span;
- var diagnostic;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) {
- diagnostic = doChange(t, sourceFile, span.start, program.getTypeChecker());
- });
- return diagnostic ? [codefix.createCodeFixAction(fixId, changes, diagnostic, fixId, ts.Diagnostics.Fix_all_implicit_this_errors)] : ts.emptyArray;
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- doChange(changes, diag.file, diag.start, context.program.getTypeChecker());
- }); },
- });
- function doChange(changes, sourceFile, pos, checker) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- ts.Debug.assert(token.kind === 104 /* ThisKeyword */);
- var fn = ts.getThisContainer(token, /*includeArrowFunctions*/ false);
- if (!ts.isFunctionDeclaration(fn) && !ts.isFunctionExpression(fn))
- return undefined;
- if (!ts.isSourceFile(ts.getThisContainer(fn, /*includeArrowFunctions*/ false))) { // 'this' is defined outside, convert to arrow function
- var fnKeyword = ts.Debug.assertDefined(ts.findChildOfKind(fn, 94 /* FunctionKeyword */, sourceFile));
- var name = fn.name;
- var body = ts.Debug.assertDefined(fn.body); // Should be defined because the function contained a 'this' expression
- if (ts.isFunctionExpression(fn)) {
- if (name && ts.FindAllReferences.Core.isSymbolReferencedInFile(name, checker, sourceFile, body)) {
- // Function expression references itself. To fix we would have to extract it to a const.
- return undefined;
- }
- // `function() {}` --> `() => {}`
- changes.delete(sourceFile, fnKeyword);
- if (name) {
- changes.delete(sourceFile, name);
- }
- changes.insertText(sourceFile, body.pos, " =>");
- return [ts.Diagnostics.Convert_function_expression_0_to_arrow_function, name ? name.text : ts.ANONYMOUS];
- }
- else {
- // `function f() {}` => `const f = () => {}`
- // `name` should be defined because we only do this in inner contexts, and name is only undefined for `export default function() {}`.
- changes.replaceNode(sourceFile, fnKeyword, ts.createToken(81 /* ConstKeyword */));
- changes.insertText(sourceFile, name.end, " = ");
- changes.insertText(sourceFile, body.pos, " =>");
- return [ts.Diagnostics.Convert_function_declaration_0_to_arrow_function, name.text];
- }
- }
- // No outer 'this', add a @class tag if in a JS constructor function
- else if (ts.isSourceFileJS(sourceFile) && ts.isPropertyAccessExpression(token.parent) && ts.isAssignmentExpression(token.parent.parent)) {
- codefix.addJSDocTags(changes, sourceFile, fn, [ts.createJSDocClassTag()]);
- return ts.Diagnostics.Add_class_tag;
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixSpelling";
- var errorCodes = [
- ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2.code,
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1.code,
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code,
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code,
- ts.Diagnostics.Module_0_has_no_exported_member_1_Did_you_mean_2.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var info = getInfo(sourceFile, context.span.start, context);
- if (!info)
- return undefined;
- var node = info.node, suggestedSymbol = info.suggestedSymbol;
- var target = context.host.getCompilationSettings().target;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, node, suggestedSymbol, target); });
- return [codefix.createCodeFixAction("spelling", changes, [ts.Diagnostics.Change_spelling_to_0, ts.symbolName(suggestedSymbol)], fixId, ts.Diagnostics.Fix_all_detected_spelling_errors)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var info = getInfo(diag.file, diag.start, context);
- var target = context.host.getCompilationSettings().target;
- if (info)
- doChange(changes, context.sourceFile, info.node, info.suggestedSymbol, target);
- }); },
- });
- function getInfo(sourceFile, pos, context) {
- // This is the identifier of the misspelled word. eg:
- // this.speling = 1;
- // ^^^^^^^
- var node = ts.getTokenAtPosition(sourceFile, pos);
- var parent = node.parent;
- var checker = context.program.getTypeChecker();
- var suggestedSymbol;
- if (ts.isPropertyAccessExpression(parent) && parent.name === node) {
- ts.Debug.assert(ts.isIdentifierOrPrivateIdentifier(node), "Expected an identifier for spelling (property access)");
- var containingType = checker.getTypeAtLocation(parent.expression);
- if (parent.flags & 32 /* OptionalChain */) {
- containingType = checker.getNonNullableType(containingType);
- }
- suggestedSymbol = checker.getSuggestedSymbolForNonexistentProperty(node, containingType);
- }
- else if (ts.isImportSpecifier(parent) && parent.name === node) {
- ts.Debug.assertNode(node, ts.isIdentifier, "Expected an identifier for spelling (import)");
- var importDeclaration = ts.findAncestor(node, ts.isImportDeclaration);
- var resolvedSourceFile = getResolvedSourceFileFromImportDeclaration(sourceFile, context, importDeclaration);
- if (resolvedSourceFile && resolvedSourceFile.symbol) {
- suggestedSymbol = checker.getSuggestedSymbolForNonexistentModule(node, resolvedSourceFile.symbol);
- }
- }
- else {
- var meaning = ts.getMeaningFromLocation(node);
- var name = ts.getTextOfNode(node);
- ts.Debug.assert(name !== undefined, "name should be defined");
- suggestedSymbol = checker.getSuggestedSymbolForNonexistentSymbol(node, name, convertSemanticMeaningToSymbolFlags(meaning));
- }
- return suggestedSymbol === undefined ? undefined : { node: node, suggestedSymbol: suggestedSymbol };
- }
- function doChange(changes, sourceFile, node, suggestedSymbol, target) {
- var suggestion = ts.symbolName(suggestedSymbol);
- if (!ts.isIdentifierText(suggestion, target) && ts.isPropertyAccessExpression(node.parent)) {
- var valDecl = suggestedSymbol.valueDeclaration;
- if (ts.isNamedDeclaration(valDecl) && ts.isPrivateIdentifier(valDecl.name)) {
- changes.replaceNode(sourceFile, node, ts.createIdentifier(suggestion));
- }
- else {
- changes.replaceNode(sourceFile, node.parent, ts.createElementAccess(node.parent.expression, ts.createLiteral(suggestion)));
- }
- }
- else {
- changes.replaceNode(sourceFile, node, ts.createIdentifier(suggestion));
- }
- }
- function convertSemanticMeaningToSymbolFlags(meaning) {
- var flags = 0;
- if (meaning & 4 /* Namespace */) {
- flags |= 1920 /* Namespace */;
- }
- if (meaning & 2 /* Type */) {
- flags |= 788968 /* Type */;
- }
- if (meaning & 1 /* Value */) {
- flags |= 111551 /* Value */;
- }
- return flags;
- }
- function getResolvedSourceFileFromImportDeclaration(sourceFile, context, importDeclaration) {
- if (!importDeclaration || !ts.isStringLiteralLike(importDeclaration.moduleSpecifier))
- return undefined;
- var resolvedModule = ts.getResolvedModule(sourceFile, importDeclaration.moduleSpecifier.text);
- if (!resolvedModule)
- return undefined;
- return context.program.getSourceFile(resolvedModule.resolvedFileName);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "returnValueCorrect";
- var fixIdAddReturnStatement = "fixAddReturnStatement";
- var fixIdRemoveBlockBodyBrace = "fixRemoveBlockBodyBrace";
- var fixIdWrapTheBlockWithParen = "fixWrapTheBlockWithParen";
- var errorCodes = [
- ts.Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value.code,
- ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code,
- ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code
- ];
- var ProblemKind;
- (function (ProblemKind) {
- ProblemKind[ProblemKind["MissingReturnStatement"] = 0] = "MissingReturnStatement";
- ProblemKind[ProblemKind["MissingParentheses"] = 1] = "MissingParentheses";
- })(ProblemKind || (ProblemKind = {}));
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- fixIds: [fixIdAddReturnStatement, fixIdRemoveBlockBodyBrace, fixIdWrapTheBlockWithParen],
- getCodeActions: function (context) {
- var program = context.program, sourceFile = context.sourceFile, start = context.span.start, errorCode = context.errorCode;
- var info = getInfo(program.getTypeChecker(), sourceFile, start, errorCode);
- if (!info)
- return undefined;
- if (info.kind === ProblemKind.MissingReturnStatement) {
- return ts.append([getActionForfixAddReturnStatement(context, info.expression, info.statement)], ts.isArrowFunction(info.declaration) ? getActionForfixRemoveBlockBodyBrace(context, info.declaration, info.expression, info.commentSource) : undefined);
- }
- else {
- return [getActionForfixWrapTheBlockWithParen(context, info.declaration, info.expression)];
- }
- },
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var info = getInfo(context.program.getTypeChecker(), diag.file, diag.start, diag.code);
- if (!info)
- return undefined;
- switch (context.fixId) {
- case fixIdAddReturnStatement:
- addReturnStatement(changes, diag.file, info.expression, info.statement);
- break;
- case fixIdRemoveBlockBodyBrace:
- if (!ts.isArrowFunction(info.declaration))
- return undefined;
- removeBlockBodyBrace(changes, diag.file, info.declaration, info.expression, info.commentSource, /* withParen */ false);
- break;
- case fixIdWrapTheBlockWithParen:
- if (!ts.isArrowFunction(info.declaration))
- return undefined;
- wrapBlockWithParen(changes, diag.file, info.declaration, info.expression);
- break;
- default:
- ts.Debug.fail(JSON.stringify(context.fixId));
- }
- }); },
- });
- function getFixInfo(checker, declaration, expectType, isFunctionType) {
- if (!declaration.body || !ts.isBlock(declaration.body) || ts.length(declaration.body.statements) !== 1)
- return undefined;
- var firstStatement = ts.first(declaration.body.statements);
- if (ts.isExpressionStatement(firstStatement) && checkFixedAssignableTo(checker, declaration, firstStatement.expression, expectType, isFunctionType)) {
- return {
- declaration: declaration,
- kind: ProblemKind.MissingReturnStatement,
- expression: firstStatement.expression,
- statement: firstStatement,
- commentSource: firstStatement.expression
- };
- }
- else if (ts.isLabeledStatement(firstStatement) && ts.isExpressionStatement(firstStatement.statement)) {
- var node = ts.createObjectLiteral([ts.createPropertyAssignment(firstStatement.label, firstStatement.statement.expression)]);
- if (checkFixedAssignableTo(checker, declaration, node, expectType, isFunctionType)) {
- return ts.isArrowFunction(declaration) ? {
- declaration: declaration,
- kind: ProblemKind.MissingParentheses,
- expression: node,
- statement: firstStatement,
- commentSource: firstStatement.statement.expression
- } : {
- declaration: declaration,
- kind: ProblemKind.MissingReturnStatement,
- expression: node,
- statement: firstStatement,
- commentSource: firstStatement.statement.expression
- };
- }
- }
- else if (ts.isBlock(firstStatement) && ts.length(firstStatement.statements) === 1) {
- var firstBlockStatement = ts.first(firstStatement.statements);
- if (ts.isLabeledStatement(firstBlockStatement) && ts.isExpressionStatement(firstBlockStatement.statement)) {
- var node = ts.createObjectLiteral([ts.createPropertyAssignment(firstBlockStatement.label, firstBlockStatement.statement.expression)]);
- if (checkFixedAssignableTo(checker, declaration, node, expectType, isFunctionType)) {
- return {
- declaration: declaration,
- kind: ProblemKind.MissingReturnStatement,
- expression: node,
- statement: firstStatement,
- commentSource: firstBlockStatement
- };
- }
- }
- }
- return undefined;
- }
- function checkFixedAssignableTo(checker, declaration, expr, type, isFunctionType) {
- return checker.isTypeAssignableTo(checker.getTypeAtLocation(isFunctionType ? ts.updateFunctionLikeBody(declaration, ts.createBlock([ts.createReturn(expr)])) : expr), type);
- }
- function getInfo(checker, sourceFile, position, errorCode) {
- var node = ts.getTokenAtPosition(sourceFile, position);
- if (!node.parent)
- return undefined;
- var declaration = ts.findAncestor(node.parent, ts.isFunctionLikeDeclaration);
- switch (errorCode) {
- case ts.Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value.code:
- if (!declaration || !declaration.body || !declaration.type || !ts.rangeContainsRange(declaration.type, node))
- return undefined;
- return getFixInfo(checker, declaration, checker.getTypeFromTypeNode(declaration.type), /* isFunctionType */ false);
- case ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code:
- if (!declaration || !ts.isCallExpression(declaration.parent) || !declaration.body)
- return undefined;
- var pos = declaration.parent.arguments.indexOf(declaration);
- var type = checker.getContextualTypeForArgumentAtIndex(declaration.parent, pos);
- if (!type)
- return undefined;
- return getFixInfo(checker, declaration, type, /* isFunctionType */ true);
- case ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code:
- if (!ts.isDeclarationName(node) || !ts.isVariableLike(node.parent) && !ts.isJsxAttribute(node.parent))
- return undefined;
- var initializer = getVariableLikeInitializer(node.parent);
- if (!initializer || !ts.isFunctionLikeDeclaration(initializer) || !initializer.body)
- return undefined;
- return getFixInfo(checker, initializer, checker.getTypeAtLocation(node.parent), /* isFunctionType */ true);
- }
- return undefined;
- }
- function getVariableLikeInitializer(declaration) {
- switch (declaration.kind) {
- case 242 /* VariableDeclaration */:
- case 156 /* Parameter */:
- case 191 /* BindingElement */:
- case 159 /* PropertyDeclaration */:
- case 281 /* PropertyAssignment */:
- return declaration.initializer;
- case 273 /* JsxAttribute */:
- return declaration.initializer && (ts.isJsxExpression(declaration.initializer) ? declaration.initializer.expression : undefined);
- case 282 /* ShorthandPropertyAssignment */:
- case 158 /* PropertySignature */:
- case 284 /* EnumMember */:
- case 323 /* JSDocPropertyTag */:
- case 317 /* JSDocParameterTag */:
- return undefined;
- }
- }
- function addReturnStatement(changes, sourceFile, expression, statement) {
- ts.suppressLeadingAndTrailingTrivia(expression);
- var probablyNeedSemi = ts.probablyUsesSemicolons(sourceFile);
- changes.replaceNode(sourceFile, statement, ts.createReturn(expression), {
- leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude,
- trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude,
- suffix: probablyNeedSemi ? ";" : undefined
- });
- }
- function removeBlockBodyBrace(changes, sourceFile, declaration, expression, commentSource, withParen) {
- var newBody = (withParen || ts.needsParentheses(expression)) ? ts.createParen(expression) : expression;
- ts.suppressLeadingAndTrailingTrivia(commentSource);
- ts.copyComments(commentSource, newBody);
- changes.replaceNode(sourceFile, declaration.body, newBody);
- }
- function wrapBlockWithParen(changes, sourceFile, declaration, expression) {
- changes.replaceNode(sourceFile, declaration.body, ts.createParen(expression));
- }
- function getActionForfixAddReturnStatement(context, expression, statement) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addReturnStatement(t, context.sourceFile, expression, statement); });
- return codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_a_return_statement, fixIdAddReturnStatement, ts.Diagnostics.Add_all_missing_return_statement);
- }
- function getActionForfixRemoveBlockBodyBrace(context, declaration, expression, commentSource) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return removeBlockBodyBrace(t, context.sourceFile, declaration, expression, commentSource, /* withParen */ false); });
- return codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Remove_block_body_braces, fixIdRemoveBlockBodyBrace, ts.Diagnostics.Remove_all_incorrect_body_block_braces);
- }
- function getActionForfixWrapTheBlockWithParen(context, declaration, expression) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return wrapBlockWithParen(t, context.sourceFile, declaration, expression); });
- return codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Wrap_the_following_body_with_parentheses_which_should_be_an_object_literal, fixIdWrapTheBlockWithParen, ts.Diagnostics.Wrap_all_object_literal_with_parentheses);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixName = "addMissingMember";
- var errorCodes = [
- ts.Diagnostics.Property_0_does_not_exist_on_type_1.code,
- ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2.code,
- ts.Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2.code,
- ts.Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2.code,
- ts.Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more.code
- ];
- var fixId = "addMissingMember";
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var info = getInfo(context.sourceFile, context.span.start, context.program.getTypeChecker(), context.program);
- if (!info)
- return undefined;
- if (info.kind === 0 /* Enum */) {
- var token_1 = info.token, parentDeclaration_1 = info.parentDeclaration;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addEnumMemberDeclaration(t, context.program.getTypeChecker(), token_1, parentDeclaration_1); });
- return [codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_missing_enum_member_0, token_1.text], fixId, ts.Diagnostics.Add_all_missing_members)];
- }
- var parentDeclaration = info.parentDeclaration, declSourceFile = info.declSourceFile, inJs = info.inJs, makeStatic = info.makeStatic, token = info.token, call = info.call;
- var methodCodeAction = call && getActionForMethodDeclaration(context, declSourceFile, parentDeclaration, token, call, makeStatic, inJs);
- var addMember = inJs && !ts.isInterfaceDeclaration(parentDeclaration) ?
- ts.singleElementArray(getActionsForAddMissingMemberInJavascriptFile(context, declSourceFile, parentDeclaration, token, makeStatic)) :
- getActionsForAddMissingMemberInTypeScriptFile(context, declSourceFile, parentDeclaration, token, makeStatic);
- return ts.concatenate(ts.singleElementArray(methodCodeAction), addMember);
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var program = context.program;
- var checker = program.getTypeChecker();
- var seen = ts.createMap();
- var typeDeclToMembers = new ts.NodeMap();
- return codefix.createCombinedCodeActions(ts.textChanges.ChangeTracker.with(context, function (changes) {
- codefix.eachDiagnostic(context, errorCodes, function (diag) {
- var info = getInfo(diag.file, diag.start, checker, context.program);
- if (!info || !ts.addToSeen(seen, ts.getNodeId(info.parentDeclaration) + "#" + info.token.text)) {
- return;
- }
- if (info.kind === 0 /* Enum */) {
- var token = info.token, parentDeclaration = info.parentDeclaration;
- addEnumMemberDeclaration(changes, checker, token, parentDeclaration);
- }
- else {
- var parentDeclaration = info.parentDeclaration, token_2 = info.token;
- var infos = typeDeclToMembers.getOrUpdate(parentDeclaration, function () { return []; });
- if (!infos.some(function (i) { return i.token.text === token_2.text; }))
- infos.push(info);
- }
- });
- typeDeclToMembers.forEach(function (infos, classDeclaration) {
- var supers = getAllSupers(classDeclaration, checker);
- var _loop_13 = function (info) {
- // If some superclass added this property, don't add it again.
- if (supers.some(function (superClassOrInterface) {
- var superInfos = typeDeclToMembers.get(superClassOrInterface);
- return !!superInfos && superInfos.some(function (_a) {
- var token = _a.token;
- return token.text === info.token.text;
- });
- }))
- return "continue";
- var parentDeclaration = info.parentDeclaration, declSourceFile = info.declSourceFile, inJs = info.inJs, makeStatic = info.makeStatic, token = info.token, call = info.call;
- // Always prefer to add a method declaration if possible.
- if (call && !ts.isPrivateIdentifier(token)) {
- addMethodDeclaration(context, changes, declSourceFile, parentDeclaration, token, call, makeStatic, inJs);
- }
- else {
- if (inJs && !ts.isInterfaceDeclaration(parentDeclaration)) {
- addMissingMemberInJs(changes, declSourceFile, parentDeclaration, token, makeStatic);
- }
- else {
- var typeNode = getTypeNode(program.getTypeChecker(), parentDeclaration, token);
- addPropertyDeclaration(changes, declSourceFile, parentDeclaration, token.text, typeNode, makeStatic ? 32 /* Static */ : 0);
- }
- }
- };
- for (var _i = 0, infos_1 = infos; _i < infos_1.length; _i++) {
- var info = infos_1[_i];
- _loop_13(info);
- }
- });
- }));
- },
- });
- function getAllSupers(decl, checker) {
- var res = [];
- while (decl) {
- var superElement = ts.getClassExtendsHeritageElement(decl);
- var superSymbol = superElement && checker.getSymbolAtLocation(superElement.expression);
- var superDecl = superSymbol && ts.find(superSymbol.declarations, ts.isClassLike);
- if (superDecl) {
- res.push(superDecl);
- }
- decl = superDecl;
- }
- return res;
- }
- var InfoKind;
- (function (InfoKind) {
- InfoKind[InfoKind["Enum"] = 0] = "Enum";
- InfoKind[InfoKind["ClassOrInterface"] = 1] = "ClassOrInterface";
- })(InfoKind || (InfoKind = {}));
- function getInfo(tokenSourceFile, tokenPos, checker, program) {
- // The identifier of the missing property. eg:
- // this.missing = 1;
- // ^^^^^^^
- var token = ts.getTokenAtPosition(tokenSourceFile, tokenPos);
- if (!ts.isIdentifier(token) && !ts.isPrivateIdentifier(token)) {
- return undefined;
- }
- var parent = token.parent;
- if (!ts.isPropertyAccessExpression(parent))
- return undefined;
- var leftExpressionType = ts.skipConstraint(checker.getTypeAtLocation(parent.expression));
- var symbol = leftExpressionType.symbol;
- if (!symbol || !symbol.declarations)
- return undefined;
- var classDeclaration = ts.find(symbol.declarations, ts.isClassLike);
- // Don't suggest adding private identifiers to anything other than a class.
- if (!classDeclaration && ts.isPrivateIdentifier(token)) {
- return undefined;
- }
- // Prefer to change the class instead of the interface if they are merged
- var classOrInterface = classDeclaration || ts.find(symbol.declarations, ts.isInterfaceDeclaration);
- if (classOrInterface && !program.isSourceFileFromExternalLibrary(classOrInterface.getSourceFile())) {
- var makeStatic = (leftExpressionType.target || leftExpressionType) !== checker.getDeclaredTypeOfSymbol(symbol);
- if (makeStatic && (ts.isPrivateIdentifier(token) || ts.isInterfaceDeclaration(classOrInterface))) {
- return undefined;
- }
- var declSourceFile = classOrInterface.getSourceFile();
- var inJs = ts.isSourceFileJS(declSourceFile);
- var call = ts.tryCast(parent.parent, ts.isCallExpression);
- return { kind: 1 /* ClassOrInterface */, token: token, parentDeclaration: classOrInterface, makeStatic: makeStatic, declSourceFile: declSourceFile, inJs: inJs, call: call };
- }
- var enumDeclaration = ts.find(symbol.declarations, ts.isEnumDeclaration);
- if (enumDeclaration && !ts.isPrivateIdentifier(token) && !program.isSourceFileFromExternalLibrary(enumDeclaration.getSourceFile())) {
- return { kind: 0 /* Enum */, token: token, parentDeclaration: enumDeclaration };
- }
- return undefined;
- }
- function getActionsForAddMissingMemberInJavascriptFile(context, declSourceFile, classDeclaration, token, makeStatic) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addMissingMemberInJs(t, declSourceFile, classDeclaration, token, makeStatic); });
- if (changes.length === 0) {
- return undefined;
- }
- var diagnostic = makeStatic ? ts.Diagnostics.Initialize_static_property_0 :
- ts.isPrivateIdentifier(token) ? ts.Diagnostics.Declare_a_private_field_named_0 : ts.Diagnostics.Initialize_property_0_in_the_constructor;
- return codefix.createCodeFixAction(fixName, changes, [diagnostic, token.text], fixId, ts.Diagnostics.Add_all_missing_members);
- }
- function addMissingMemberInJs(changeTracker, declSourceFile, classDeclaration, token, makeStatic) {
- var tokenName = token.text;
- if (makeStatic) {
- if (classDeclaration.kind === 214 /* ClassExpression */) {
- return;
- }
- var className = classDeclaration.name.getText();
- var staticInitialization = initializePropertyToUndefined(ts.createIdentifier(className), tokenName);
- changeTracker.insertNodeAfter(declSourceFile, classDeclaration, staticInitialization);
- }
- else if (ts.isPrivateIdentifier(token)) {
- var property = ts.createProperty(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, tokenName,
- /*questionToken*/ undefined,
- /*type*/ undefined,
- /*initializer*/ undefined);
- var lastProp = getNodeToInsertPropertyAfter(classDeclaration);
- if (lastProp) {
- changeTracker.insertNodeAfter(declSourceFile, lastProp, property);
- }
- else {
- changeTracker.insertNodeAtClassStart(declSourceFile, classDeclaration, property);
- }
- }
- else {
- var classConstructor = ts.getFirstConstructorWithBody(classDeclaration);
- if (!classConstructor) {
- return;
- }
- var propertyInitialization = initializePropertyToUndefined(ts.createThis(), tokenName);
- changeTracker.insertNodeAtConstructorEnd(declSourceFile, classConstructor, propertyInitialization);
- }
- }
- function initializePropertyToUndefined(obj, propertyName) {
- return ts.createStatement(ts.createAssignment(ts.createPropertyAccess(obj, propertyName), ts.createIdentifier("undefined")));
- }
- function getActionsForAddMissingMemberInTypeScriptFile(context, declSourceFile, classDeclaration, token, makeStatic) {
- var typeNode = getTypeNode(context.program.getTypeChecker(), classDeclaration, token);
- var actions = [createAddPropertyDeclarationAction(context, declSourceFile, classDeclaration, token.text, typeNode, makeStatic ? 32 /* Static */ : 0)];
- if (makeStatic || ts.isPrivateIdentifier(token)) {
- return actions;
- }
- if (ts.startsWithUnderscore(token.text)) {
- actions.unshift(createAddPropertyDeclarationAction(context, declSourceFile, classDeclaration, token.text, typeNode, 8 /* Private */));
- }
- actions.push(createAddIndexSignatureAction(context, declSourceFile, classDeclaration, token.text, typeNode));
- return actions;
- }
- function getTypeNode(checker, classDeclaration, token) {
- var typeNode;
- if (token.parent.parent.kind === 209 /* BinaryExpression */) {
- var binaryExpression = token.parent.parent;
- var otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left;
- var widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)));
- typeNode = checker.typeToTypeNode(widenedType, classDeclaration, /*flags*/ undefined);
- }
- else {
- var contextualType = checker.getContextualType(token.parent);
- typeNode = contextualType ? checker.typeToTypeNode(contextualType, /*enclosingDeclaration*/ undefined, /*flags*/ undefined) : undefined;
- }
- return typeNode || ts.createKeywordTypeNode(125 /* AnyKeyword */);
- }
- function createAddPropertyDeclarationAction(context, declSourceFile, classDeclaration, tokenName, typeNode, modifierFlags) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addPropertyDeclaration(t, declSourceFile, classDeclaration, tokenName, typeNode, modifierFlags); });
- if (modifierFlags & 8 /* Private */) {
- return codefix.createCodeFixActionWithoutFixAll(fixName, changes, [ts.Diagnostics.Declare_private_property_0, tokenName]);
- }
- return codefix.createCodeFixAction(fixName, changes, [modifierFlags & 32 /* Static */ ? ts.Diagnostics.Declare_static_property_0 : ts.Diagnostics.Declare_property_0, tokenName], fixId, ts.Diagnostics.Add_all_missing_members);
- }
- function addPropertyDeclaration(changeTracker, declSourceFile, classDeclaration, tokenName, typeNode, modifierFlags) {
- var property = ts.createProperty(
- /*decorators*/ undefined,
- /*modifiers*/ modifierFlags ? ts.createNodeArray(ts.createModifiersFromModifierFlags(modifierFlags)) : undefined, tokenName,
- /*questionToken*/ undefined, typeNode,
- /*initializer*/ undefined);
- var lastProp = getNodeToInsertPropertyAfter(classDeclaration);
- if (lastProp) {
- changeTracker.insertNodeAfter(declSourceFile, lastProp, property);
- }
- else {
- changeTracker.insertNodeAtClassStart(declSourceFile, classDeclaration, property);
- }
- }
- // Gets the last of the first run of PropertyDeclarations, or undefined if the class does not start with a PropertyDeclaration.
- function getNodeToInsertPropertyAfter(cls) {
- var res;
- for (var _i = 0, _a = cls.members; _i < _a.length; _i++) {
- var member = _a[_i];
- if (!ts.isPropertyDeclaration(member))
- break;
- res = member;
- }
- return res;
- }
- function createAddIndexSignatureAction(context, declSourceFile, classDeclaration, tokenName, typeNode) {
- // Index signatures cannot have the static modifier.
- var stringTypeNode = ts.createKeywordTypeNode(143 /* StringKeyword */);
- var indexingParameter = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- /*dotDotDotToken*/ undefined, "x",
- /*questionToken*/ undefined, stringTypeNode,
- /*initializer*/ undefined);
- var indexSignature = ts.createIndexSignature(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, [indexingParameter], typeNode);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.insertNodeAtClassStart(declSourceFile, classDeclaration, indexSignature); });
- // No fixId here because code-fix-all currently only works on adding individual named properties.
- return codefix.createCodeFixActionWithoutFixAll(fixName, changes, [ts.Diagnostics.Add_index_signature_for_property_0, tokenName]);
- }
- function getActionForMethodDeclaration(context, declSourceFile, classDeclaration, token, callExpression, makeStatic, inJs) {
- // Private methods are not implemented yet.
- if (ts.isPrivateIdentifier(token)) {
- return undefined;
- }
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addMethodDeclaration(context, t, declSourceFile, classDeclaration, token, callExpression, makeStatic, inJs); });
- return codefix.createCodeFixAction(fixName, changes, [makeStatic ? ts.Diagnostics.Declare_static_method_0 : ts.Diagnostics.Declare_method_0, token.text], fixId, ts.Diagnostics.Add_all_missing_members);
- }
- function addMethodDeclaration(context, changeTracker, declSourceFile, typeDecl, token, callExpression, makeStatic, inJs) {
- var importAdder = codefix.createImportAdder(declSourceFile, context.program, context.preferences, context.host);
- var methodDeclaration = codefix.createMethodFromCallExpression(context, callExpression, token.text, inJs, makeStatic, typeDecl, importAdder);
- var containingMethodDeclaration = ts.getAncestor(callExpression, 161 /* MethodDeclaration */);
- if (containingMethodDeclaration && containingMethodDeclaration.parent === typeDecl) {
- changeTracker.insertNodeAfter(declSourceFile, containingMethodDeclaration, methodDeclaration);
- }
- else {
- changeTracker.insertNodeAtClassStart(declSourceFile, typeDecl, methodDeclaration);
- }
- importAdder.writeFixes(changeTracker);
- }
- function addEnumMemberDeclaration(changes, checker, token, enumDeclaration) {
- /**
- * create initializer only literal enum that has string initializer.
- * value of initializer is a string literal that equal to name of enum member.
- * numeric enum or empty enum will not create initializer.
- */
- var hasStringInitializer = ts.some(enumDeclaration.members, function (member) {
- var type = checker.getTypeAtLocation(member);
- return !!(type && type.flags & 132 /* StringLike */);
- });
- var enumMember = ts.createEnumMember(token, hasStringInitializer ? ts.createStringLiteral(token.text) : undefined);
- changes.replaceNode(enumDeclaration.getSourceFile(), enumDeclaration, ts.updateEnumDeclaration(enumDeclaration, enumDeclaration.decorators, enumDeclaration.modifiers, enumDeclaration.name, ts.concatenate(enumDeclaration.members, ts.singleElementArray(enumMember))), {
- leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll,
- trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude
- });
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addMissingNewOperator";
- var errorCodes = [ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addMissingNewOperator(t, sourceFile, span); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_missing_new_operator_to_call, fixId, ts.Diagnostics.Add_missing_new_operator_to_all_calls)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- return addMissingNewOperator(changes, context.sourceFile, diag);
- }); },
- });
- function addMissingNewOperator(changes, sourceFile, span) {
- var call = ts.cast(findAncestorMatchingSpan(sourceFile, span), ts.isCallExpression);
- var newExpression = ts.createNew(call.expression, call.typeArguments, call.arguments);
- changes.replaceNode(sourceFile, call, newExpression);
- }
- function findAncestorMatchingSpan(sourceFile, span) {
- var token = ts.getTokenAtPosition(sourceFile, span.start);
- var end = ts.textSpanEnd(span);
- while (token.end < end) {
- token = token.parent;
- }
- return token;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixName = "fixCannotFindModule";
- var fixIdInstallTypesPackage = "installTypesPackage";
- var errorCodeCannotFindModule = ts.Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations.code;
- var errorCodes = [
- errorCodeCannotFindModule,
- ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var host = context.host, sourceFile = context.sourceFile, start = context.span.start;
- var packageName = tryGetImportedPackageName(sourceFile, start);
- if (packageName === undefined)
- return undefined;
- var typesPackageName = getTypesPackageNameToInstall(packageName, host, context.errorCode);
- return typesPackageName === undefined
- ? []
- : [codefix.createCodeFixAction(fixName, /*changes*/ [], [ts.Diagnostics.Install_0, typesPackageName], fixIdInstallTypesPackage, ts.Diagnostics.Install_all_missing_types_packages, getInstallCommand(sourceFile.fileName, typesPackageName))];
- },
- fixIds: [fixIdInstallTypesPackage],
- getAllCodeActions: function (context) {
- return codefix.codeFixAll(context, errorCodes, function (_changes, diag, commands) {
- var packageName = tryGetImportedPackageName(diag.file, diag.start);
- if (packageName === undefined)
- return undefined;
- switch (context.fixId) {
- case fixIdInstallTypesPackage: {
- var pkg = getTypesPackageNameToInstall(packageName, context.host, diag.code);
- if (pkg) {
- commands.push(getInstallCommand(diag.file.fileName, pkg));
- }
- break;
- }
- default:
- ts.Debug.fail("Bad fixId: " + context.fixId);
- }
- });
- },
- });
- function getInstallCommand(fileName, packageName) {
- return { type: "install package", file: fileName, packageName: packageName };
- }
- function tryGetImportedPackageName(sourceFile, pos) {
- var moduleName = ts.cast(ts.getTokenAtPosition(sourceFile, pos), ts.isStringLiteral).text;
- var packageName = ts.parsePackageName(moduleName).packageName;
- return ts.isExternalModuleNameRelative(packageName) ? undefined : packageName;
- }
- function getTypesPackageNameToInstall(packageName, host, diagCode) {
- return diagCode === errorCodeCannotFindModule
- ? (ts.JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined)
- : (host.isKnownTypesPackageName(packageName) ? ts.getTypesPackageName(packageName) : undefined); // TODO: GH#18217
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodes = [
- ts.Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2.code,
- ts.Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1.code,
- ];
- var fixId = "fixClassDoesntImplementInheritedAbstractMember";
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) {
- return addMissingMembers(getClass(sourceFile, span.start), sourceFile, context, t, context.preferences);
- });
- return changes.length === 0 ? undefined : [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Implement_inherited_abstract_class, fixId, ts.Diagnostics.Implement_all_inherited_abstract_classes)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var seenClassDeclarations = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var classDeclaration = getClass(diag.file, diag.start);
- if (ts.addToSeen(seenClassDeclarations, ts.getNodeId(classDeclaration))) {
- addMissingMembers(classDeclaration, context.sourceFile, context, changes, context.preferences);
- }
- });
- },
- });
- function getClass(sourceFile, pos) {
- // Token is the identifier in the case of a class declaration
- // or the class keyword token in the case of a class expression.
- var token = ts.getTokenAtPosition(sourceFile, pos);
- return ts.cast(token.parent, ts.isClassLike);
- }
- function addMissingMembers(classDeclaration, sourceFile, context, changeTracker, preferences) {
- var extendsNode = ts.getEffectiveBaseTypeNode(classDeclaration);
- var checker = context.program.getTypeChecker();
- var instantiatedExtendsType = checker.getTypeAtLocation(extendsNode);
- // Note that this is ultimately derived from a map indexed by symbol names,
- // so duplicates cannot occur.
- var abstractAndNonPrivateExtendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType).filter(symbolPointsToNonPrivateAndAbstractMember);
- var importAdder = codefix.createImportAdder(sourceFile, context.program, preferences, context.host);
- codefix.createMissingMemberNodes(classDeclaration, abstractAndNonPrivateExtendsSymbols, context, preferences, importAdder, function (member) { return changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member); });
- importAdder.writeFixes(changeTracker);
- }
- function symbolPointsToNonPrivateAndAbstractMember(symbol) {
- // See `codeFixClassExtendAbstractProtectedProperty.ts` in https://github.com/Microsoft/TypeScript/pull/11547/files
- // (now named `codeFixClassExtendAbstractPrivateProperty.ts`)
- var flags = ts.getModifierFlags(ts.first(symbol.getDeclarations()));
- return !(flags & 8 /* Private */) && !!(flags & 128 /* Abstract */);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "classSuperMustPrecedeThisAccess";
- var errorCodes = [ts.Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var nodes = getNodes(sourceFile, span.start);
- if (!nodes)
- return undefined;
- var constructor = nodes.constructor, superCall = nodes.superCall;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, constructor, superCall); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Make_super_call_the_first_statement_in_the_constructor, fixId, ts.Diagnostics.Make_all_super_calls_the_first_statement_in_their_constructor)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var seenClasses = ts.createMap(); // Ensure we only do this once per class.
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var nodes = getNodes(diag.file, diag.start);
- if (!nodes)
- return;
- var constructor = nodes.constructor, superCall = nodes.superCall;
- if (ts.addToSeen(seenClasses, ts.getNodeId(constructor.parent))) {
- doChange(changes, sourceFile, constructor, superCall);
- }
- });
- },
- });
- function doChange(changes, sourceFile, constructor, superCall) {
- changes.insertNodeAtConstructorStart(sourceFile, constructor, superCall);
- changes.delete(sourceFile, superCall);
- }
- function getNodes(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- if (token.kind !== 104 /* ThisKeyword */)
- return undefined;
- var constructor = ts.getContainingFunction(token);
- var superCall = findSuperCall(constructor.body);
- // figure out if the `this` access is actually inside the supercall
- // i.e. super(this.a), since in that case we won't suggest a fix
- return superCall && !superCall.expression.arguments.some(function (arg) { return ts.isPropertyAccessExpression(arg) && arg.expression === token; }) ? { constructor: constructor, superCall: superCall } : undefined;
- }
- function findSuperCall(n) {
- return ts.isExpressionStatement(n) && ts.isSuperCall(n.expression)
- ? n
- : ts.isFunctionLike(n)
- ? undefined
- : ts.forEachChild(n, findSuperCall);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "constructorForDerivedNeedSuperCall";
- var errorCodes = [ts.Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var ctr = getNode(sourceFile, span.start);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, ctr); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_missing_super_call, fixId, ts.Diagnostics.Add_all_missing_super_calls)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- return doChange(changes, context.sourceFile, getNode(diag.file, diag.start));
- }); },
- });
- function getNode(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- ts.Debug.assert(ts.isConstructorDeclaration(token.parent), "token should be at the constructor declaration");
- return token.parent;
- }
- function doChange(changes, sourceFile, ctr) {
- var superCall = ts.createStatement(ts.createCall(ts.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ ts.emptyArray));
- changes.insertNodeAtConstructorStart(sourceFile, ctr, superCall);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "enableExperimentalDecorators";
- var errorCodes = [
- ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning.code
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var configFile = context.program.getCompilerOptions().configFile;
- if (configFile === undefined) {
- return undefined;
- }
- var changes = ts.textChanges.ChangeTracker.with(context, function (changeTracker) { return doChange(changeTracker, configFile); });
- return [codefix.createCodeFixActionWithoutFixAll(fixId, changes, ts.Diagnostics.Enable_the_experimentalDecorators_option_in_your_configuration_file)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes) {
- var configFile = context.program.getCompilerOptions().configFile;
- if (configFile === undefined) {
- return undefined;
- }
- doChange(changes, configFile);
- }); },
- });
- function doChange(changeTracker, configFile) {
- codefix.setJsonCompilerOptionValue(changeTracker, configFile, "experimentalDecorators", ts.createTrue());
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixID = "fixEnableJsxFlag";
- var errorCodes = [ts.Diagnostics.Cannot_use_JSX_unless_the_jsx_flag_is_provided.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var configFile = context.program.getCompilerOptions().configFile;
- if (configFile === undefined) {
- return undefined;
- }
- var changes = ts.textChanges.ChangeTracker.with(context, function (changeTracker) {
- return doChange(changeTracker, configFile);
- });
- return [
- codefix.createCodeFixActionWithoutFixAll(fixID, changes, ts.Diagnostics.Enable_the_jsx_flag_in_your_configuration_file)
- ];
- },
- fixIds: [fixID],
- getAllCodeActions: function (context) {
- return codefix.codeFixAll(context, errorCodes, function (changes) {
- var configFile = context.program.getCompilerOptions().configFile;
- if (configFile === undefined) {
- return undefined;
- }
- doChange(changes, configFile);
- });
- }
- });
- function doChange(changeTracker, configFile) {
- codefix.setJsonCompilerOptionValue(changeTracker, configFile, "jsx", ts.createStringLiteral("react"));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- codefix.registerCodeFix({
- errorCodes: [ts.Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_esnext_or_system_and_the_target_option_is_set_to_es2017_or_higher.code],
- getCodeActions: function (context) {
- var compilerOptions = context.program.getCompilerOptions();
- var configFile = compilerOptions.configFile;
- if (configFile === undefined) {
- return undefined;
- }
- var codeFixes = [];
- var moduleKind = ts.getEmitModuleKind(compilerOptions);
- var moduleOutOfRange = moduleKind >= ts.ModuleKind.ES2015 && moduleKind < ts.ModuleKind.ESNext;
- if (moduleOutOfRange) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (changes) {
- codefix.setJsonCompilerOptionValue(changes, configFile, "module", ts.createStringLiteral("esnext"));
- });
- codeFixes.push(codefix.createCodeFixActionWithoutFixAll("fixModuleOption", changes, [ts.Diagnostics.Set_the_module_option_in_your_configuration_file_to_0, "esnext"]));
- }
- var target = ts.getEmitScriptTarget(compilerOptions);
- var targetOutOfRange = target < 4 /* ES2017 */ || target > 99 /* ESNext */;
- if (targetOutOfRange) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (tracker) {
- var configObject = ts.getTsConfigObjectLiteralExpression(configFile);
- if (!configObject)
- return;
- var options = [["target", ts.createStringLiteral("es2017")]];
- if (moduleKind === ts.ModuleKind.CommonJS) {
- // Ensure we preserve the default module kind (commonjs), as targets >= ES2015 have a default module kind of es2015.
- options.push(["module", ts.createStringLiteral("commonjs")]);
- }
- codefix.setJsonCompilerOptionValues(tracker, configFile, options);
- });
- codeFixes.push(codefix.createCodeFixActionWithoutFixAll("fixTargetOption", changes, [ts.Diagnostics.Set_the_target_option_in_your_configuration_file_to_0, "es2017"]));
- }
- return codeFixes.length ? codeFixes : undefined;
- }
- });
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "extendsInterfaceBecomesImplements";
- var errorCodes = [ts.Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var nodes = getNodes(sourceFile, context.span.start);
- if (!nodes)
- return undefined;
- var extendsToken = nodes.extendsToken, heritageClauses = nodes.heritageClauses;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChanges(t, sourceFile, extendsToken, heritageClauses); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Change_extends_to_implements, fixId, ts.Diagnostics.Change_all_extended_interfaces_to_implements)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var nodes = getNodes(diag.file, diag.start);
- if (nodes)
- doChanges(changes, diag.file, nodes.extendsToken, nodes.heritageClauses);
- }); },
- });
- function getNodes(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- var heritageClauses = ts.getContainingClass(token).heritageClauses;
- var extendsToken = heritageClauses[0].getFirstToken();
- return extendsToken.kind === 90 /* ExtendsKeyword */ ? { extendsToken: extendsToken, heritageClauses: heritageClauses } : undefined;
- }
- function doChanges(changes, sourceFile, extendsToken, heritageClauses) {
- changes.replaceNode(sourceFile, extendsToken, ts.createToken(113 /* ImplementsKeyword */));
- // If there is already an implements clause, replace the implements keyword with a comma.
- if (heritageClauses.length === 2 &&
- heritageClauses[0].token === 90 /* ExtendsKeyword */ &&
- heritageClauses[1].token === 113 /* ImplementsKeyword */) {
- var implementsToken = heritageClauses[1].getFirstToken();
- var implementsFullStart = implementsToken.getFullStart();
- changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, ts.createToken(27 /* CommaToken */));
- // Rough heuristic: delete trailing whitespace after keyword so that it's not excessive.
- // (Trailing because leading might be indentation, which is more sensitive.)
- var text = sourceFile.text;
- var end = implementsToken.end;
- while (end < text.length && ts.isWhiteSpaceSingleLine(text.charCodeAt(end))) {
- end++;
- }
- changes.deleteRange(sourceFile, { pos: implementsToken.getStart(), end: end });
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "forgottenThisPropertyAccess";
- var didYouMeanStaticMemberCode = ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0.code;
- var errorCodes = [
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code,
- ts.Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies.code,
- didYouMeanStaticMemberCode,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var info = getInfo(sourceFile, context.span.start, context.errorCode);
- if (!info) {
- return undefined;
- }
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, info); });
- return [codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Add_0_to_unresolved_variable, info.className || "this"], fixId, ts.Diagnostics.Add_qualifier_to_all_unresolved_variables_matching_a_member_name)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var info = getInfo(diag.file, diag.start, diag.code);
- if (info)
- doChange(changes, context.sourceFile, info);
- }); },
- });
- function getInfo(sourceFile, pos, diagCode) {
- var node = ts.getTokenAtPosition(sourceFile, pos);
- if (ts.isIdentifier(node)) {
- return { node: node, className: diagCode === didYouMeanStaticMemberCode ? ts.getContainingClass(node).name.text : undefined };
- }
- }
- function doChange(changes, sourceFile, _a) {
- var node = _a.node, className = _a.className;
- // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper
- ts.suppressLeadingAndTrailingTrivia(node);
- changes.replaceNode(sourceFile, node, ts.createPropertyAccess(className ? ts.createIdentifier(className) : ts.createThis(), node));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixIdExpression = "fixInvalidJsxCharacters_expression";
- var fixIdHtmlEntity = "fixInvalidJsxCharacters_htmlEntity";
- var errorCodes = [
- ts.Diagnostics.Unexpected_token_Did_you_mean_or_gt.code,
- ts.Diagnostics.Unexpected_token_Did_you_mean_or_rbrace.code
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- fixIds: [fixIdExpression, fixIdHtmlEntity],
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, preferences = context.preferences, span = context.span;
- var changeToExpression = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, preferences, sourceFile, span.start, /* useHtmlEntity */ false); });
- var changeToHtmlEntity = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, preferences, sourceFile, span.start, /* useHtmlEntity */ true); });
- return [
- codefix.createCodeFixAction(fixIdExpression, changeToExpression, ts.Diagnostics.Wrap_invalid_character_in_an_expression_container, fixIdExpression, ts.Diagnostics.Wrap_all_invalid_characters_in_an_expression_container),
- codefix.createCodeFixAction(fixIdHtmlEntity, changeToHtmlEntity, ts.Diagnostics.Convert_invalid_character_to_its_html_entity_code, fixIdHtmlEntity, ts.Diagnostics.Convert_all_invalid_characters_to_HTML_entity_code)
- ];
- },
- getAllCodeActions: function (context) {
- return codefix.codeFixAll(context, errorCodes, function (changes, diagnostic) { return doChange(changes, context.preferences, diagnostic.file, diagnostic.start, context.fixId === fixIdHtmlEntity); });
- }
- });
- var htmlEntity = {
- ">": ">",
- "}": "}",
- };
- function isValidCharacter(character) {
- return ts.hasProperty(htmlEntity, character);
- }
- function doChange(changes, preferences, sourceFile, start, useHtmlEntity) {
- var character = sourceFile.getText()[start];
- // sanity check
- if (!isValidCharacter(character)) {
- return;
- }
- var replacement = useHtmlEntity ? htmlEntity[character] : "{" + ts.quote(character, preferences) + "}";
- changes.replaceRangeWithText(sourceFile, { pos: start, end: start + 1 }, replacement);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixName = "unusedIdentifier";
- var fixIdPrefix = "unusedIdentifier_prefix";
- var fixIdDelete = "unusedIdentifier_delete";
- var fixIdInfer = "unusedIdentifier_infer";
- var errorCodes = [
- ts.Diagnostics._0_is_declared_but_its_value_is_never_read.code,
- ts.Diagnostics._0_is_declared_but_never_used.code,
- ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code,
- ts.Diagnostics.All_imports_in_import_declaration_are_unused.code,
- ts.Diagnostics.All_destructured_elements_are_unused.code,
- ts.Diagnostics.All_variables_are_unused.code,
- ts.Diagnostics.All_type_parameters_are_unused.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var errorCode = context.errorCode, sourceFile = context.sourceFile, program = context.program;
- var checker = program.getTypeChecker();
- var sourceFiles = program.getSourceFiles();
- var token = ts.getTokenAtPosition(sourceFile, context.span.start);
- if (ts.isJSDocTemplateTag(token)) {
- return [createDeleteFix(ts.textChanges.ChangeTracker.with(context, function (t) { return t.delete(sourceFile, token); }), ts.Diagnostics.Remove_template_tag)];
- }
- if (token.kind === 29 /* LessThanToken */) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return deleteTypeParameters(t, sourceFile, token); });
- return [createDeleteFix(changes, ts.Diagnostics.Remove_type_parameters)];
- }
- var importDecl = tryGetFullImport(token);
- if (importDecl) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.delete(sourceFile, importDecl); });
- return [createDeleteFix(changes, [ts.Diagnostics.Remove_import_from_0, ts.showModuleSpecifier(importDecl)])];
- }
- var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) {
- return tryDeleteFullDestructure(token, t, sourceFile, checker, sourceFiles, /*isFixAll*/ false);
- });
- if (delDestructure.length) {
- return [createDeleteFix(delDestructure, ts.Diagnostics.Remove_destructuring)];
- }
- var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(sourceFile, token, t); });
- if (delVar.length) {
- return [createDeleteFix(delVar, ts.Diagnostics.Remove_variable_statement)];
- }
- var result = [];
- if (token.kind === 132 /* InferKeyword */) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return changeInferToUnknown(t, sourceFile, token); });
- var name = ts.cast(token.parent, ts.isInferTypeNode).typeParameter.name.text;
- result.push(codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Replace_infer_0_with_unknown, name], fixIdInfer, ts.Diagnostics.Replace_all_unused_infer_with_unknown));
- }
- else {
- var deletion = ts.textChanges.ChangeTracker.with(context, function (t) {
- return tryDeleteDeclaration(sourceFile, token, t, checker, sourceFiles, /*isFixAll*/ false);
- });
- if (deletion.length) {
- var name = ts.isComputedPropertyName(token.parent) ? token.parent : token;
- result.push(createDeleteFix(deletion, [ts.Diagnostics.Remove_unused_declaration_for_Colon_0, name.getText(sourceFile)]));
- }
- }
- var prefix = ts.textChanges.ChangeTracker.with(context, function (t) { return tryPrefixDeclaration(t, errorCode, sourceFile, token); });
- if (prefix.length) {
- result.push(codefix.createCodeFixAction(fixName, prefix, [ts.Diagnostics.Prefix_0_with_an_underscore, token.getText(sourceFile)], fixIdPrefix, ts.Diagnostics.Prefix_all_unused_declarations_with_where_possible));
- }
- return result;
- },
- fixIds: [fixIdPrefix, fixIdDelete, fixIdInfer],
- getAllCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program;
- var checker = program.getTypeChecker();
- var sourceFiles = program.getSourceFiles();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var token = ts.getTokenAtPosition(sourceFile, diag.start);
- switch (context.fixId) {
- case fixIdPrefix:
- tryPrefixDeclaration(changes, diag.code, sourceFile, token);
- break;
- case fixIdDelete: {
- if (token.kind === 132 /* InferKeyword */)
- break; // Can't delete
- var importDecl = tryGetFullImport(token);
- if (importDecl) {
- changes.delete(sourceFile, importDecl);
- }
- else if (ts.isJSDocTemplateTag(token)) {
- changes.delete(sourceFile, token);
- }
- else if (token.kind === 29 /* LessThanToken */) {
- deleteTypeParameters(changes, sourceFile, token);
- }
- else if (!tryDeleteFullDestructure(token, changes, sourceFile, checker, sourceFiles, /*isFixAll*/ true) &&
- !tryDeleteFullVariableStatement(sourceFile, token, changes)) {
- tryDeleteDeclaration(sourceFile, token, changes, checker, sourceFiles, /*isFixAll*/ true);
- }
- break;
- }
- case fixIdInfer:
- if (token.kind === 132 /* InferKeyword */) {
- changeInferToUnknown(changes, sourceFile, token);
- }
- break;
- default:
- ts.Debug.fail(JSON.stringify(context.fixId));
- }
- });
- },
- });
- function changeInferToUnknown(changes, sourceFile, token) {
- changes.replaceNode(sourceFile, token.parent, ts.createKeywordTypeNode(148 /* UnknownKeyword */));
- }
- function createDeleteFix(changes, diag) {
- return codefix.createCodeFixAction(fixName, changes, diag, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations);
- }
- function deleteTypeParameters(changes, sourceFile, token) {
- changes.delete(sourceFile, ts.Debug.checkDefined(ts.cast(token.parent, ts.isDeclarationWithTypeParameterChildren).typeParameters, "The type parameter to delete should exist"));
- }
- // Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing.
- function tryGetFullImport(token) {
- return token.kind === 96 /* ImportKeyword */ ? ts.tryCast(token.parent, ts.isImportDeclaration) : undefined;
- }
- function tryDeleteFullDestructure(token, changes, sourceFile, checker, sourceFiles, isFixAll) {
- if (token.kind !== 18 /* OpenBraceToken */ || !ts.isObjectBindingPattern(token.parent))
- return false;
- var decl = token.parent.parent;
- if (decl.kind === 156 /* Parameter */) {
- tryDeleteParameter(changes, sourceFile, decl, checker, sourceFiles, isFixAll);
- }
- else {
- changes.delete(sourceFile, decl);
- }
- return true;
- }
- function tryDeleteFullVariableStatement(sourceFile, token, changes) {
- var declarationList = ts.tryCast(token.parent, ts.isVariableDeclarationList);
- if (declarationList && declarationList.getChildren(sourceFile)[0] === token) {
- changes.delete(sourceFile, declarationList.parent.kind === 225 /* VariableStatement */ ? declarationList.parent : declarationList);
- return true;
- }
- return false;
- }
- function tryPrefixDeclaration(changes, errorCode, sourceFile, token) {
- // Don't offer to prefix a property.
- if (errorCode === ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code)
- return;
- if (token.kind === 132 /* InferKeyword */) {
- token = ts.cast(token.parent, ts.isInferTypeNode).typeParameter.name;
- }
- if (ts.isIdentifier(token) && canPrefix(token)) {
- changes.replaceNode(sourceFile, token, ts.createIdentifier("_" + token.text));
- if (ts.isParameter(token.parent)) {
- ts.getJSDocParameterTags(token.parent).forEach(function (tag) {
- if (ts.isIdentifier(tag.name)) {
- changes.replaceNode(sourceFile, tag.name, ts.createIdentifier("_" + tag.name.text));
- }
- });
- }
- }
- }
- function canPrefix(token) {
- switch (token.parent.kind) {
- case 156 /* Parameter */:
- case 155 /* TypeParameter */:
- return true;
- case 242 /* VariableDeclaration */: {
- var varDecl = token.parent;
- switch (varDecl.parent.parent.kind) {
- case 232 /* ForOfStatement */:
- case 231 /* ForInStatement */:
- return true;
- }
- }
- }
- return false;
- }
- function tryDeleteDeclaration(sourceFile, token, changes, checker, sourceFiles, isFixAll) {
- tryDeleteDeclarationWorker(token, changes, sourceFile, checker, sourceFiles, isFixAll);
- if (ts.isIdentifier(token))
- deleteAssignments(changes, sourceFile, token, checker);
- }
- function deleteAssignments(changes, sourceFile, token, checker) {
- ts.FindAllReferences.Core.eachSymbolReferenceInFile(token, checker, sourceFile, function (ref) {
- if (ts.isPropertyAccessExpression(ref.parent) && ref.parent.name === ref)
- ref = ref.parent;
- if (ts.isBinaryExpression(ref.parent) && ts.isExpressionStatement(ref.parent.parent) && ref.parent.left === ref) {
- changes.delete(sourceFile, ref.parent.parent);
- }
- });
- }
- function tryDeleteDeclarationWorker(token, changes, sourceFile, checker, sourceFiles, isFixAll) {
- var parent = token.parent;
- if (ts.isParameter(parent)) {
- tryDeleteParameter(changes, sourceFile, parent, checker, sourceFiles, isFixAll);
- }
- else {
- changes.delete(sourceFile, ts.isImportClause(parent) ? token : ts.isComputedPropertyName(parent) ? parent.parent : parent);
- }
- }
- function tryDeleteParameter(changes, sourceFile, p, checker, sourceFiles, isFixAll) {
- if (mayDeleteParameter(p, checker, isFixAll)) {
- if (p.modifiers && p.modifiers.length > 0
- && (!ts.isIdentifier(p.name) || ts.FindAllReferences.Core.isSymbolReferencedInFile(p.name, checker, sourceFile))) {
- p.modifiers.forEach(function (modifier) {
- changes.deleteModifier(sourceFile, modifier);
- });
- }
- else {
- changes.delete(sourceFile, p);
- deleteUnusedArguments(changes, sourceFile, p, sourceFiles, checker);
- }
- }
- }
- function mayDeleteParameter(p, checker, isFixAll) {
- var parent = p.parent;
- switch (parent.kind) {
- case 161 /* MethodDeclaration */:
- // Don't remove a parameter if this overrides something.
- var symbol = checker.getSymbolAtLocation(parent.name);
- if (ts.isMemberSymbolInBaseType(symbol, checker))
- return false;
- // falls through
- case 162 /* Constructor */:
- case 244 /* FunctionDeclaration */:
- return true;
- case 201 /* FunctionExpression */:
- case 202 /* ArrowFunction */: {
- // Can't remove a non-last parameter in a callback. Can remove a parameter in code-fix-all if future parameters are also unused.
- var parameters = parent.parameters;
- var index = parameters.indexOf(p);
- ts.Debug.assert(index !== -1, "The parameter should already be in the list");
- return isFixAll
- ? parameters.slice(index + 1).every(function (p) { return p.name.kind === 75 /* Identifier */ && !p.symbol.isReferenced; })
- : index === parameters.length - 1;
- }
- case 164 /* SetAccessor */:
- // Setter must have a parameter
- return false;
- default:
- return ts.Debug.failBadSyntaxKind(parent);
- }
- }
- function deleteUnusedArguments(changes, sourceFile, deletedParameter, sourceFiles, checker) {
- ts.FindAllReferences.Core.eachSignatureCall(deletedParameter.parent, sourceFiles, checker, function (call) {
- var index = deletedParameter.parent.parameters.indexOf(deletedParameter);
- if (call.arguments.length > index) { // Just in case the call didn't provide enough arguments.
- changes.delete(sourceFile, call.arguments[index]);
- }
- });
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixUnreachableCode";
- var errorCodes = [ts.Diagnostics.Unreachable_code_detected.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, context.span.start, context.span.length, context.errorCode); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Remove_unreachable_code, fixId, ts.Diagnostics.Remove_all_unreachable_code)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, diag.start, diag.length, diag.code); }); },
- });
- function doChange(changes, sourceFile, start, length, errorCode) {
- var token = ts.getTokenAtPosition(sourceFile, start);
- var statement = ts.findAncestor(token, ts.isStatement);
- if (statement.getStart(sourceFile) !== token.getStart(sourceFile)) {
- var logData = JSON.stringify({
- statementKind: ts.Debug.formatSyntaxKind(statement.kind),
- tokenKind: ts.Debug.formatSyntaxKind(token.kind),
- errorCode: errorCode,
- start: start,
- length: length
- });
- ts.Debug.fail("Token and statement should start at the same point. " + logData);
- }
- var container = (ts.isBlock(statement.parent) ? statement.parent : statement).parent;
- if (!ts.isBlock(statement.parent) || statement === ts.first(statement.parent.statements)) {
- switch (container.kind) {
- case 227 /* IfStatement */:
- if (container.elseStatement) {
- if (ts.isBlock(statement.parent)) {
- break;
- }
- else {
- changes.replaceNode(sourceFile, statement, ts.createBlock(ts.emptyArray));
- }
- return;
- }
- // falls through
- case 229 /* WhileStatement */:
- case 230 /* ForStatement */:
- changes.delete(sourceFile, container);
- return;
- }
- }
- if (ts.isBlock(statement.parent)) {
- var end_3 = start + length;
- var lastStatement = ts.Debug.checkDefined(lastWhere(ts.sliceAfter(statement.parent.statements, statement), function (s) { return s.pos < end_3; }), "Some statement should be last");
- changes.deleteNodeRange(sourceFile, statement, lastStatement);
- }
- else {
- changes.delete(sourceFile, statement);
- }
- }
- function lastWhere(a, pred) {
- var last;
- for (var _i = 0, a_1 = a; _i < a_1.length; _i++) {
- var value = a_1[_i];
- if (!pred(value))
- break;
- last = value;
- }
- return last;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixUnusedLabel";
- var errorCodes = [ts.Diagnostics.Unused_label.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, context.span.start); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Remove_unused_label, fixId, ts.Diagnostics.Remove_all_unused_labels)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, diag.start); }); },
- });
- function doChange(changes, sourceFile, start) {
- var token = ts.getTokenAtPosition(sourceFile, start);
- var labeledStatement = ts.cast(token.parent, ts.isLabeledStatement);
- var pos = token.getStart(sourceFile);
- var statementPos = labeledStatement.statement.getStart(sourceFile);
- // If label is on a separate line, just delete the rest of that line, but not the indentation of the labeled statement.
- var end = ts.positionsAreOnSameLine(pos, statementPos, sourceFile) ? statementPos
- : ts.skipTrivia(sourceFile.text, ts.findChildOfKind(labeledStatement, 58 /* ColonToken */, sourceFile).end, /*stopAfterLineBreak*/ true);
- changes.deleteRange(sourceFile, { pos: pos, end: end });
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixIdPlain = "fixJSDocTypes_plain";
- var fixIdNullable = "fixJSDocTypes_nullable";
- var errorCodes = [ts.Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var checker = context.program.getTypeChecker();
- var info = getInfo(sourceFile, context.span.start, checker);
- if (!info)
- return undefined;
- var typeNode = info.typeNode, type = info.type;
- var original = typeNode.getText(sourceFile);
- var actions = [fix(type, fixIdPlain, ts.Diagnostics.Change_all_jsdoc_style_types_to_TypeScript)];
- if (typeNode.kind === 297 /* JSDocNullableType */) {
- // for nullable types, suggest the flow-compatible `T | null | undefined`
- // in addition to the jsdoc/closure-compatible `T | null`
- actions.push(fix(checker.getNullableType(type, 32768 /* Undefined */), fixIdNullable, ts.Diagnostics.Change_all_jsdoc_style_types_to_TypeScript_and_add_undefined_to_nullable_types));
- }
- return actions;
- function fix(type, fixId, fixAllDescription) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, typeNode, type, checker); });
- return codefix.createCodeFixAction("jdocTypes", changes, [ts.Diagnostics.Change_0_to_1, original, checker.typeToString(type)], fixId, fixAllDescription);
- }
- },
- fixIds: [fixIdPlain, fixIdNullable],
- getAllCodeActions: function (context) {
- var fixId = context.fixId, program = context.program, sourceFile = context.sourceFile;
- var checker = program.getTypeChecker();
- return codefix.codeFixAll(context, errorCodes, function (changes, err) {
- var info = getInfo(err.file, err.start, checker);
- if (!info)
- return;
- var typeNode = info.typeNode, type = info.type;
- var fixedType = typeNode.kind === 297 /* JSDocNullableType */ && fixId === fixIdNullable ? checker.getNullableType(type, 32768 /* Undefined */) : type;
- doChange(changes, sourceFile, typeNode, fixedType, checker);
- });
- }
- });
- function doChange(changes, sourceFile, oldTypeNode, newType, checker) {
- changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode, /*flags*/ undefined)); // TODO: GH#18217
- }
- function getInfo(sourceFile, pos, checker) {
- var decl = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos), isTypeContainer);
- var typeNode = decl && decl.type;
- return typeNode && { typeNode: typeNode, type: checker.getTypeFromTypeNode(typeNode) };
- }
- function isTypeContainer(node) {
- // NOTE: Some locations are not handled yet:
- // MappedTypeNode.typeParameters and SignatureDeclaration.typeParameters, as well as CallExpression.typeArguments
- switch (node.kind) {
- case 217 /* AsExpression */:
- case 165 /* CallSignature */:
- case 166 /* ConstructSignature */:
- case 244 /* FunctionDeclaration */:
- case 163 /* GetAccessor */:
- case 167 /* IndexSignature */:
- case 186 /* MappedType */:
- case 161 /* MethodDeclaration */:
- case 160 /* MethodSignature */:
- case 156 /* Parameter */:
- case 159 /* PropertyDeclaration */:
- case 158 /* PropertySignature */:
- case 164 /* SetAccessor */:
- case 247 /* TypeAliasDeclaration */:
- case 199 /* TypeAssertionExpression */:
- case 242 /* VariableDeclaration */:
- return true;
- default:
- return false;
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixMissingCallParentheses";
- var errorCodes = [
- ts.Diagnostics.This_condition_will_always_return_true_since_the_function_is_always_defined_Did_you_mean_to_call_it_instead.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- fixIds: [fixId],
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var callName = getCallName(sourceFile, span.start);
- if (!callName)
- return;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, callName); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_missing_call_parentheses, fixId, ts.Diagnostics.Add_all_missing_call_parentheses)];
- },
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var callName = getCallName(diag.file, diag.start);
- if (callName)
- doChange(changes, diag.file, callName);
- }); }
- });
- function doChange(changes, sourceFile, name) {
- changes.replaceNodeWithText(sourceFile, name, name.text + "()");
- }
- function getCallName(sourceFile, start) {
- var token = ts.getTokenAtPosition(sourceFile, start);
- if (ts.isPropertyAccessExpression(token.parent)) {
- var current = token.parent;
- while (ts.isPropertyAccessExpression(current.parent)) {
- current = current.parent;
- }
- return current.name;
- }
- if (ts.isIdentifier(token)) {
- return token;
- }
- return undefined;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixAwaitInSyncFunction";
- var errorCodes = [
- ts.Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules.code,
- ts.Diagnostics.A_for_await_of_statement_is_only_allowed_within_an_async_function_or_async_generator.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var nodes = getNodes(sourceFile, span.start);
- if (!nodes)
- return undefined;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, nodes); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_async_modifier_to_containing_function, fixId, ts.Diagnostics.Add_all_missing_async_modifiers)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var seen = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var nodes = getNodes(diag.file, diag.start);
- if (!nodes || !ts.addToSeen(seen, ts.getNodeId(nodes.insertBefore)))
- return;
- doChange(changes, context.sourceFile, nodes);
- });
- },
- });
- function getReturnType(expr) {
- if (expr.type) {
- return expr.type;
- }
- if (ts.isVariableDeclaration(expr.parent) &&
- expr.parent.type &&
- ts.isFunctionTypeNode(expr.parent.type)) {
- return expr.parent.type.type;
- }
- }
- function getNodes(sourceFile, start) {
- var token = ts.getTokenAtPosition(sourceFile, start);
- var containingFunction = ts.getContainingFunction(token);
- if (!containingFunction) {
- return;
- }
- var insertBefore;
- switch (containingFunction.kind) {
- case 161 /* MethodDeclaration */:
- insertBefore = containingFunction.name;
- break;
- case 244 /* FunctionDeclaration */:
- case 201 /* FunctionExpression */:
- insertBefore = ts.findChildOfKind(containingFunction, 94 /* FunctionKeyword */, sourceFile);
- break;
- case 202 /* ArrowFunction */:
- insertBefore = ts.findChildOfKind(containingFunction, 20 /* OpenParenToken */, sourceFile) || ts.first(containingFunction.parameters);
- break;
- default:
- return;
- }
- return insertBefore && {
- insertBefore: insertBefore,
- returnType: getReturnType(containingFunction)
- };
- }
- function doChange(changes, sourceFile, _a) {
- var insertBefore = _a.insertBefore, returnType = _a.returnType;
- if (returnType) {
- var entityName = ts.getEntityNameFromTypeNode(returnType);
- if (!entityName || entityName.kind !== 75 /* Identifier */ || entityName.text !== "Promise") {
- changes.replaceNode(sourceFile, returnType, ts.createTypeReferenceNode("Promise", ts.createNodeArray([returnType])));
- }
- }
- changes.insertModifierBefore(sourceFile, 126 /* AsyncKeyword */, insertBefore);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "inferFromUsage";
- var errorCodes = [
- // Variable declarations
- ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code,
- // Variable uses
- ts.Diagnostics.Variable_0_implicitly_has_an_1_type.code,
- // Parameter declarations
- ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code,
- ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code,
- // Get Accessor declarations
- ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code,
- ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code,
- // Set Accessor declarations
- ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code,
- // Property declarations
- ts.Diagnostics.Member_0_implicitly_has_an_1_type.code,
- //// Suggestions
- // Variable declarations
- ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code,
- // Variable uses
- ts.Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
- // Parameter declarations
- ts.Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
- ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code,
- // Get Accessor declarations
- ts.Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code,
- ts.Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage.code,
- // Set Accessor declarations
- ts.Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code,
- // Property declarations
- ts.Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code,
- // Function expressions and declarations
- ts.Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, start = context.span.start, errorCode = context.errorCode, cancellationToken = context.cancellationToken, host = context.host, preferences = context.preferences;
- var token = ts.getTokenAtPosition(sourceFile, start);
- var declaration;
- var changes = ts.textChanges.ChangeTracker.with(context, function (changes) { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken, /*markSeen*/ ts.returnTrue, host, preferences); });
- var name = declaration && ts.getNameOfDeclaration(declaration);
- return !name || changes.length === 0 ? undefined
- : [codefix.createCodeFixAction(fixId, changes, [getDiagnostic(errorCode, token), name.getText(sourceFile)], fixId, ts.Diagnostics.Infer_all_types_from_usage)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, cancellationToken = context.cancellationToken, host = context.host, preferences = context.preferences;
- var markSeen = ts.nodeSeenTracker();
- return codefix.codeFixAll(context, errorCodes, function (changes, err) {
- doChange(changes, sourceFile, ts.getTokenAtPosition(err.file, err.start), err.code, program, cancellationToken, markSeen, host, preferences);
- });
- },
- });
- function getDiagnostic(errorCode, token) {
- switch (errorCode) {
- case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
- case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
- return ts.isSetAccessorDeclaration(ts.getContainingFunction(token)) ? ts.Diagnostics.Infer_type_of_0_from_usage : ts.Diagnostics.Infer_parameter_types_from_usage; // TODO: GH#18217
- case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
- case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code:
- return ts.Diagnostics.Infer_parameter_types_from_usage;
- case ts.Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code:
- return ts.Diagnostics.Infer_this_type_of_0_from_usage;
- default:
- return ts.Diagnostics.Infer_type_of_0_from_usage;
- }
- }
- /** Map suggestion code to error code */
- function mapSuggestionDiagnostic(errorCode) {
- switch (errorCode) {
- case ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_but_a_better_type_may_be_inferred_from_usage.code:
- return ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code;
- case ts.Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
- return ts.Diagnostics.Variable_0_implicitly_has_an_1_type.code;
- case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
- return ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code;
- case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage.code:
- return ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code;
- case ts.Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_get_accessor_may_be_inferred_from_usage.code:
- return ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code;
- case ts.Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage.code:
- return ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code;
- case ts.Diagnostics.Property_0_implicitly_has_type_any_but_a_better_type_for_its_set_accessor_may_be_inferred_from_usage.code:
- return ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code;
- case ts.Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage.code:
- return ts.Diagnostics.Member_0_implicitly_has_an_1_type.code;
- }
- return errorCode;
- }
- function doChange(changes, sourceFile, token, errorCode, program, cancellationToken, markSeen, host, preferences) {
- if (!ts.isParameterPropertyModifier(token.kind) && token.kind !== 75 /* Identifier */ && token.kind !== 25 /* DotDotDotToken */ && token.kind !== 104 /* ThisKeyword */) {
- return undefined;
- }
- var parent = token.parent;
- var importAdder = codefix.createImportAdder(sourceFile, program, preferences, host);
- errorCode = mapSuggestionDiagnostic(errorCode);
- switch (errorCode) {
- // Variable and Property declarations
- case ts.Diagnostics.Member_0_implicitly_has_an_1_type.code:
- case ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code:
- if ((ts.isVariableDeclaration(parent) && markSeen(parent)) || ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent)) { // handle bad location
- annotateVariableDeclaration(changes, importAdder, sourceFile, parent, program, host, cancellationToken);
- importAdder.writeFixes(changes);
- return parent;
- }
- if (ts.isPropertyAccessExpression(parent)) {
- var type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken);
- var typeNode = ts.getTypeNodeIfAccessible(type, parent, program, host);
- if (typeNode) {
- // Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags
- var typeTag = ts.createJSDocTypeTag(ts.createJSDocTypeExpression(typeNode), /*comment*/ "");
- addJSDocTags(changes, sourceFile, ts.cast(parent.parent.parent, ts.isExpressionStatement), [typeTag]);
- }
- importAdder.writeFixes(changes);
- return parent;
- }
- return undefined;
- case ts.Diagnostics.Variable_0_implicitly_has_an_1_type.code: {
- var symbol = program.getTypeChecker().getSymbolAtLocation(token);
- if (symbol && symbol.valueDeclaration && ts.isVariableDeclaration(symbol.valueDeclaration) && markSeen(symbol.valueDeclaration)) {
- annotateVariableDeclaration(changes, importAdder, sourceFile, symbol.valueDeclaration, program, host, cancellationToken);
- importAdder.writeFixes(changes);
- return symbol.valueDeclaration;
- }
- return undefined;
- }
- }
- var containingFunction = ts.getContainingFunction(token);
- if (containingFunction === undefined) {
- return undefined;
- }
- var declaration;
- switch (errorCode) {
- // Parameter declarations
- case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
- if (ts.isSetAccessorDeclaration(containingFunction)) {
- annotateSetAccessor(changes, importAdder, sourceFile, containingFunction, program, host, cancellationToken);
- declaration = containingFunction;
- break;
- }
- // falls through
- case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
- if (markSeen(containingFunction)) {
- var param = ts.cast(parent, ts.isParameter);
- annotateParameters(changes, importAdder, sourceFile, param, containingFunction, program, host, cancellationToken);
- declaration = param;
- }
- break;
- // Get Accessor declarations
- case ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code:
- case ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code:
- if (ts.isGetAccessorDeclaration(containingFunction) && ts.isIdentifier(containingFunction.name)) {
- annotate(changes, importAdder, sourceFile, containingFunction, inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken), program, host);
- declaration = containingFunction;
- }
- break;
- // Set Accessor declarations
- case ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code:
- if (ts.isSetAccessorDeclaration(containingFunction)) {
- annotateSetAccessor(changes, importAdder, sourceFile, containingFunction, program, host, cancellationToken);
- declaration = containingFunction;
- }
- break;
- // Function 'this'
- case ts.Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code:
- if (ts.textChanges.isThisTypeAnnotatable(containingFunction) && markSeen(containingFunction)) {
- annotateThis(changes, sourceFile, containingFunction, program, host, cancellationToken);
- declaration = containingFunction;
- }
- break;
- default:
- return ts.Debug.fail(String(errorCode));
- }
- importAdder.writeFixes(changes);
- return declaration;
- }
- function annotateVariableDeclaration(changes, importAdder, sourceFile, declaration, program, host, cancellationToken) {
- if (ts.isIdentifier(declaration.name)) {
- annotate(changes, importAdder, sourceFile, declaration, inferTypeForVariableFromUsage(declaration.name, program, cancellationToken), program, host);
- }
- }
- function annotateParameters(changes, importAdder, sourceFile, parameterDeclaration, containingFunction, program, host, cancellationToken) {
- if (!ts.isIdentifier(parameterDeclaration.name)) {
- return;
- }
- var parameterInferences = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken);
- ts.Debug.assert(containingFunction.parameters.length === parameterInferences.length, "Parameter count and inference count should match");
- if (ts.isInJSFile(containingFunction)) {
- annotateJSDocParameters(changes, sourceFile, parameterInferences, program, host);
- }
- else {
- var needParens = ts.isArrowFunction(containingFunction) && !ts.findChildOfKind(containingFunction, 20 /* OpenParenToken */, sourceFile);
- if (needParens)
- changes.insertNodeBefore(sourceFile, ts.first(containingFunction.parameters), ts.createToken(20 /* OpenParenToken */));
- for (var _i = 0, parameterInferences_1 = parameterInferences; _i < parameterInferences_1.length; _i++) {
- var _a = parameterInferences_1[_i], declaration = _a.declaration, type = _a.type;
- if (declaration && !declaration.type && !declaration.initializer) {
- annotate(changes, importAdder, sourceFile, declaration, type, program, host);
- }
- }
- if (needParens)
- changes.insertNodeAfter(sourceFile, ts.last(containingFunction.parameters), ts.createToken(21 /* CloseParenToken */));
- }
- }
- function annotateThis(changes, sourceFile, containingFunction, program, host, cancellationToken) {
- var references = getFunctionReferences(containingFunction, sourceFile, program, cancellationToken);
- if (!references || !references.length) {
- return;
- }
- var thisInference = inferTypeFromReferences(program, references, cancellationToken).thisParameter();
- var typeNode = ts.getTypeNodeIfAccessible(thisInference, containingFunction, program, host);
- if (!typeNode) {
- return;
- }
- if (ts.isInJSFile(containingFunction)) {
- annotateJSDocThis(changes, sourceFile, containingFunction, typeNode);
- }
- else {
- changes.tryInsertThisTypeAnnotation(sourceFile, containingFunction, typeNode);
- }
- }
- function annotateJSDocThis(changes, sourceFile, containingFunction, typeNode) {
- addJSDocTags(changes, sourceFile, containingFunction, [
- ts.createJSDocThisTag(ts.createJSDocTypeExpression(typeNode)),
- ]);
- }
- function annotateSetAccessor(changes, importAdder, sourceFile, setAccessorDeclaration, program, host, cancellationToken) {
- var param = ts.firstOrUndefined(setAccessorDeclaration.parameters);
- if (param && ts.isIdentifier(setAccessorDeclaration.name) && ts.isIdentifier(param.name)) {
- var type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken);
- if (type === program.getTypeChecker().getAnyType()) {
- type = inferTypeForVariableFromUsage(param.name, program, cancellationToken);
- }
- if (ts.isInJSFile(setAccessorDeclaration)) {
- annotateJSDocParameters(changes, sourceFile, [{ declaration: param, type: type }], program, host);
- }
- else {
- annotate(changes, importAdder, sourceFile, param, type, program, host);
- }
- }
- }
- function annotate(changes, importAdder, sourceFile, declaration, type, program, host) {
- var typeNode = ts.getTypeNodeIfAccessible(type, declaration, program, host);
- if (typeNode) {
- if (ts.isInJSFile(sourceFile) && declaration.kind !== 158 /* PropertySignature */) {
- var parent = ts.isVariableDeclaration(declaration) ? ts.tryCast(declaration.parent.parent, ts.isVariableStatement) : declaration;
- if (!parent) {
- return;
- }
- var typeExpression = ts.createJSDocTypeExpression(typeNode);
- var typeTag = ts.isGetAccessorDeclaration(declaration) ? ts.createJSDocReturnTag(typeExpression, "") : ts.createJSDocTypeTag(typeExpression, "");
- addJSDocTags(changes, sourceFile, parent, [typeTag]);
- }
- else if (!tryReplaceImportTypeNodeWithAutoImport(typeNode, declaration, type, sourceFile, changes, importAdder, ts.getEmitScriptTarget(program.getCompilerOptions()))) {
- changes.tryInsertTypeAnnotation(sourceFile, declaration, typeNode);
- }
- }
- }
- function tryReplaceImportTypeNodeWithAutoImport(typeNode, declaration, type, sourceFile, changes, importAdder, scriptTarget) {
- var importableReference = codefix.tryGetAutoImportableReferenceFromImportTypeNode(typeNode, type, scriptTarget);
- if (importableReference && changes.tryInsertTypeAnnotation(sourceFile, declaration, importableReference.typeReference)) {
- ts.forEach(importableReference.symbols, function (s) { return importAdder.addImportFromExportedSymbol(s, /*usageIsTypeOnly*/ true); });
- return true;
- }
- return false;
- }
- function annotateJSDocParameters(changes, sourceFile, parameterInferences, program, host) {
- var signature = parameterInferences.length && parameterInferences[0].declaration.parent;
- if (!signature) {
- return;
- }
- var paramTags = ts.mapDefined(parameterInferences, function (inference) {
- var param = inference.declaration;
- // only infer parameters that have (1) no type and (2) an accessible inferred type
- if (param.initializer || ts.getJSDocType(param) || !ts.isIdentifier(param.name))
- return;
- var typeNode = inference.type && ts.getTypeNodeIfAccessible(inference.type, param, program, host);
- var name = ts.getSynthesizedClone(param.name);
- ts.setEmitFlags(name, 1536 /* NoComments */ | 2048 /* NoNestedComments */);
- return typeNode && ts.createJSDocParamTag(name, !!inference.isOptional, ts.createJSDocTypeExpression(typeNode), "");
- });
- addJSDocTags(changes, sourceFile, signature, paramTags);
- }
- function addJSDocTags(changes, sourceFile, parent, newTags) {
- var comments = ts.mapDefined(parent.jsDoc, function (j) { return j.comment; });
- var oldTags = ts.flatMapToMutable(parent.jsDoc, function (j) { return j.tags; });
- var unmergedNewTags = newTags.filter(function (newTag) { return !oldTags || !oldTags.some(function (tag, i) {
- var merged = tryMergeJsdocTags(tag, newTag);
- if (merged)
- oldTags[i] = merged;
- return !!merged;
- }); });
- var tag = ts.createJSDocComment(comments.join("\n"), ts.createNodeArray(__spreadArrays((oldTags || ts.emptyArray), unmergedNewTags)));
- var jsDocNode = parent.kind === 202 /* ArrowFunction */ ? getJsDocNodeForArrowFunction(parent) : parent;
- jsDocNode.jsDoc = parent.jsDoc;
- jsDocNode.jsDocCache = parent.jsDocCache;
- changes.insertJsdocCommentBefore(sourceFile, jsDocNode, tag);
- }
- codefix.addJSDocTags = addJSDocTags;
- function getJsDocNodeForArrowFunction(signature) {
- if (signature.parent.kind === 159 /* PropertyDeclaration */) {
- return signature.parent;
- }
- return signature.parent.parent;
- }
- function tryMergeJsdocTags(oldTag, newTag) {
- if (oldTag.kind !== newTag.kind) {
- return undefined;
- }
- switch (oldTag.kind) {
- case 317 /* JSDocParameterTag */: {
- var oldParam = oldTag;
- var newParam = newTag;
- return ts.isIdentifier(oldParam.name) && ts.isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText
- ? ts.createJSDocParamTag(newParam.name, newParam.isBracketed, newParam.typeExpression, oldParam.comment)
- : undefined;
- }
- case 318 /* JSDocReturnTag */:
- return ts.createJSDocReturnTag(newTag.typeExpression, oldTag.comment);
- }
- }
- function getReferences(token, program, cancellationToken) {
- // Position shouldn't matter since token is not a SourceFile.
- return ts.mapDefined(ts.FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), function (entry) {
- return entry.kind !== 0 /* Span */ ? ts.tryCast(entry.node, ts.isIdentifier) : undefined;
- });
- }
- function inferTypeForVariableFromUsage(token, program, cancellationToken) {
- var references = getReferences(token, program, cancellationToken);
- return inferTypeFromReferences(program, references, cancellationToken).single();
- }
- function inferTypeForParametersFromUsage(func, sourceFile, program, cancellationToken) {
- var references = getFunctionReferences(func, sourceFile, program, cancellationToken);
- return references && inferTypeFromReferences(program, references, cancellationToken).parameters(func) ||
- func.parameters.map(function (p) { return ({
- declaration: p,
- type: ts.isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : program.getTypeChecker().getAnyType()
- }); });
- }
- function getFunctionReferences(containingFunction, sourceFile, program, cancellationToken) {
- var searchToken;
- switch (containingFunction.kind) {
- case 162 /* Constructor */:
- searchToken = ts.findChildOfKind(containingFunction, 129 /* ConstructorKeyword */, sourceFile);
- break;
- case 202 /* ArrowFunction */:
- case 201 /* FunctionExpression */:
- var parent = containingFunction.parent;
- searchToken = ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name) ?
- parent.name :
- containingFunction.name;
- break;
- case 244 /* FunctionDeclaration */:
- case 161 /* MethodDeclaration */:
- searchToken = containingFunction.name;
- break;
- }
- if (!searchToken) {
- return undefined;
- }
- return getReferences(searchToken, program, cancellationToken);
- }
- function inferTypeFromReferences(program, references, cancellationToken) {
- var checker = program.getTypeChecker();
- var builtinConstructors = {
- string: function () { return checker.getStringType(); },
- number: function () { return checker.getNumberType(); },
- Array: function (t) { return checker.createArrayType(t); },
- Promise: function (t) { return checker.createPromiseType(t); },
- };
- var builtins = [
- checker.getStringType(),
- checker.getNumberType(),
- checker.createArrayType(checker.getAnyType()),
- checker.createPromiseType(checker.getAnyType()),
- ];
- return {
- single: single,
- parameters: parameters,
- thisParameter: thisParameter,
- };
- function createEmptyUsage() {
- return {
- isNumber: undefined,
- isString: undefined,
- isNumberOrString: undefined,
- candidateTypes: undefined,
- properties: undefined,
- calls: undefined,
- constructs: undefined,
- numberIndex: undefined,
- stringIndex: undefined,
- candidateThisTypes: undefined,
- inferredTypes: undefined,
- };
- }
- function combineUsages(usages) {
- var combinedProperties = ts.createUnderscoreEscapedMap();
- for (var _i = 0, usages_1 = usages; _i < usages_1.length; _i++) {
- var u = usages_1[_i];
- if (u.properties) {
- u.properties.forEach(function (p, name) {
- if (!combinedProperties.has(name)) {
- combinedProperties.set(name, []);
- }
- combinedProperties.get(name).push(p);
- });
- }
- }
- var properties = ts.createUnderscoreEscapedMap();
- combinedProperties.forEach(function (ps, name) {
- properties.set(name, combineUsages(ps));
- });
- return {
- isNumber: usages.some(function (u) { return u.isNumber; }),
- isString: usages.some(function (u) { return u.isString; }),
- isNumberOrString: usages.some(function (u) { return u.isNumberOrString; }),
- candidateTypes: ts.flatMap(usages, function (u) { return u.candidateTypes; }),
- properties: properties,
- calls: ts.flatMap(usages, function (u) { return u.calls; }),
- constructs: ts.flatMap(usages, function (u) { return u.constructs; }),
- numberIndex: ts.forEach(usages, function (u) { return u.numberIndex; }),
- stringIndex: ts.forEach(usages, function (u) { return u.stringIndex; }),
- candidateThisTypes: ts.flatMap(usages, function (u) { return u.candidateThisTypes; }),
- inferredTypes: undefined,
- };
- }
- function single() {
- return combineTypes(inferTypesFromReferencesSingle(references));
- }
- function parameters(declaration) {
- if (references.length === 0 || !declaration.parameters) {
- return undefined;
- }
- var usage = createEmptyUsage();
- for (var _i = 0, references_2 = references; _i < references_2.length; _i++) {
- var reference = references_2[_i];
- cancellationToken.throwIfCancellationRequested();
- calculateUsageOfNode(reference, usage);
- }
- var calls = __spreadArrays(usage.constructs || [], usage.calls || []);
- return declaration.parameters.map(function (parameter, parameterIndex) {
- var types = [];
- var isRest = ts.isRestParameter(parameter);
- var isOptional = false;
- for (var _i = 0, calls_1 = calls; _i < calls_1.length; _i++) {
- var call = calls_1[_i];
- if (call.argumentTypes.length <= parameterIndex) {
- isOptional = ts.isInJSFile(declaration);
- types.push(checker.getUndefinedType());
- }
- else if (isRest) {
- for (var i = parameterIndex; i < call.argumentTypes.length; i++) {
- types.push(checker.getBaseTypeOfLiteralType(call.argumentTypes[i]));
- }
- }
- else {
- types.push(checker.getBaseTypeOfLiteralType(call.argumentTypes[parameterIndex]));
- }
- }
- if (ts.isIdentifier(parameter.name)) {
- var inferred = inferTypesFromReferencesSingle(getReferences(parameter.name, program, cancellationToken));
- types.push.apply(types, (isRest ? ts.mapDefined(inferred, checker.getElementTypeOfArrayType) : inferred));
- }
- var type = combineTypes(types);
- return {
- type: isRest ? checker.createArrayType(type) : type,
- isOptional: isOptional && !isRest,
- declaration: parameter
- };
- });
- }
- function thisParameter() {
- var usage = createEmptyUsage();
- for (var _i = 0, references_3 = references; _i < references_3.length; _i++) {
- var reference = references_3[_i];
- cancellationToken.throwIfCancellationRequested();
- calculateUsageOfNode(reference, usage);
- }
- return combineTypes(usage.candidateThisTypes || ts.emptyArray);
- }
- function inferTypesFromReferencesSingle(references) {
- var usage = createEmptyUsage();
- for (var _i = 0, references_4 = references; _i < references_4.length; _i++) {
- var reference = references_4[_i];
- cancellationToken.throwIfCancellationRequested();
- calculateUsageOfNode(reference, usage);
- }
- return inferTypes(usage);
- }
- function calculateUsageOfNode(node, usage) {
- while (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) {
- node = node.parent;
- }
- switch (node.parent.kind) {
- case 226 /* ExpressionStatement */:
- inferTypeFromExpressionStatement(node, usage);
- break;
- case 208 /* PostfixUnaryExpression */:
- usage.isNumber = true;
- break;
- case 207 /* PrefixUnaryExpression */:
- inferTypeFromPrefixUnaryExpression(node.parent, usage);
- break;
- case 209 /* BinaryExpression */:
- inferTypeFromBinaryExpression(node, node.parent, usage);
- break;
- case 277 /* CaseClause */:
- case 278 /* DefaultClause */:
- inferTypeFromSwitchStatementLabel(node.parent, usage);
- break;
- case 196 /* CallExpression */:
- case 197 /* NewExpression */:
- if (node.parent.expression === node) {
- inferTypeFromCallExpression(node.parent, usage);
- }
- else {
- inferTypeFromContextualType(node, usage);
- }
- break;
- case 194 /* PropertyAccessExpression */:
- inferTypeFromPropertyAccessExpression(node.parent, usage);
- break;
- case 195 /* ElementAccessExpression */:
- inferTypeFromPropertyElementExpression(node.parent, node, usage);
- break;
- case 281 /* PropertyAssignment */:
- case 282 /* ShorthandPropertyAssignment */:
- inferTypeFromPropertyAssignment(node.parent, usage);
- break;
- case 159 /* PropertyDeclaration */:
- inferTypeFromPropertyDeclaration(node.parent, usage);
- break;
- case 242 /* VariableDeclaration */: {
- var _a = node.parent, name = _a.name, initializer = _a.initializer;
- if (node === name) {
- if (initializer) { // This can happen for `let x = null;` which still has an implicit-any error.
- addCandidateType(usage, checker.getTypeAtLocation(initializer));
- }
- break;
- }
- }
- // falls through
- default:
- return inferTypeFromContextualType(node, usage);
- }
- }
- function inferTypeFromContextualType(node, usage) {
- if (ts.isExpressionNode(node)) {
- addCandidateType(usage, checker.getContextualType(node));
- }
- }
- function inferTypeFromExpressionStatement(node, usage) {
- addCandidateType(usage, ts.isCallExpression(node) ? checker.getVoidType() : checker.getAnyType());
- }
- function inferTypeFromPrefixUnaryExpression(node, usage) {
- switch (node.operator) {
- case 45 /* PlusPlusToken */:
- case 46 /* MinusMinusToken */:
- case 40 /* MinusToken */:
- case 54 /* TildeToken */:
- usage.isNumber = true;
- break;
- case 39 /* PlusToken */:
- usage.isNumberOrString = true;
- break;
- // case SyntaxKind.ExclamationToken:
- // no inferences here;
- }
- }
- function inferTypeFromBinaryExpression(node, parent, usage) {
- switch (parent.operatorToken.kind) {
- // ExponentiationOperator
- case 42 /* AsteriskAsteriskToken */:
- // MultiplicativeOperator
- // falls through
- case 41 /* AsteriskToken */:
- case 43 /* SlashToken */:
- case 44 /* PercentToken */:
- // ShiftOperator
- // falls through
- case 47 /* LessThanLessThanToken */:
- case 48 /* GreaterThanGreaterThanToken */:
- case 49 /* GreaterThanGreaterThanGreaterThanToken */:
- // BitwiseOperator
- // falls through
- case 50 /* AmpersandToken */:
- case 51 /* BarToken */:
- case 52 /* CaretToken */:
- // CompoundAssignmentOperator
- // falls through
- case 64 /* MinusEqualsToken */:
- case 66 /* AsteriskAsteriskEqualsToken */:
- case 65 /* AsteriskEqualsToken */:
- case 67 /* SlashEqualsToken */:
- case 68 /* PercentEqualsToken */:
- case 72 /* AmpersandEqualsToken */:
- case 73 /* BarEqualsToken */:
- case 74 /* CaretEqualsToken */:
- case 69 /* LessThanLessThanEqualsToken */:
- case 71 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
- case 70 /* GreaterThanGreaterThanEqualsToken */:
- // AdditiveOperator
- // falls through
- case 40 /* MinusToken */:
- // RelationalOperator
- // falls through
- case 29 /* LessThanToken */:
- case 32 /* LessThanEqualsToken */:
- case 31 /* GreaterThanToken */:
- case 33 /* GreaterThanEqualsToken */:
- var operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left);
- if (operandType.flags & 1056 /* EnumLike */) {
- addCandidateType(usage, operandType);
- }
- else {
- usage.isNumber = true;
- }
- break;
- case 63 /* PlusEqualsToken */:
- case 39 /* PlusToken */:
- var otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left);
- if (otherOperandType.flags & 1056 /* EnumLike */) {
- addCandidateType(usage, otherOperandType);
- }
- else if (otherOperandType.flags & 296 /* NumberLike */) {
- usage.isNumber = true;
- }
- else if (otherOperandType.flags & 132 /* StringLike */) {
- usage.isString = true;
- }
- else if (otherOperandType.flags & 1 /* Any */) {
- // do nothing, maybe we'll learn something elsewhere
- }
- else {
- usage.isNumberOrString = true;
- }
- break;
- // AssignmentOperators
- case 62 /* EqualsToken */:
- case 34 /* EqualsEqualsToken */:
- case 36 /* EqualsEqualsEqualsToken */:
- case 37 /* ExclamationEqualsEqualsToken */:
- case 35 /* ExclamationEqualsToken */:
- addCandidateType(usage, checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left));
- break;
- case 97 /* InKeyword */:
- if (node === parent.left) {
- usage.isString = true;
- }
- break;
- // LogicalOperator Or NullishCoalescing
- case 56 /* BarBarToken */:
- case 60 /* QuestionQuestionToken */:
- if (node === parent.left &&
- (node.parent.parent.kind === 242 /* VariableDeclaration */ || ts.isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true))) {
- // var x = x || {};
- // TODO: use getFalsyflagsOfType
- addCandidateType(usage, checker.getTypeAtLocation(parent.right));
- }
- break;
- case 55 /* AmpersandAmpersandToken */:
- case 27 /* CommaToken */:
- case 98 /* InstanceOfKeyword */:
- // nothing to infer here
- break;
- }
- }
- function inferTypeFromSwitchStatementLabel(parent, usage) {
- addCandidateType(usage, checker.getTypeAtLocation(parent.parent.parent.expression));
- }
- function inferTypeFromCallExpression(parent, usage) {
- var call = {
- argumentTypes: [],
- return_: createEmptyUsage()
- };
- if (parent.arguments) {
- for (var _i = 0, _a = parent.arguments; _i < _a.length; _i++) {
- var argument = _a[_i];
- call.argumentTypes.push(checker.getTypeAtLocation(argument));
- }
- }
- calculateUsageOfNode(parent, call.return_);
- if (parent.kind === 196 /* CallExpression */) {
- (usage.calls || (usage.calls = [])).push(call);
- }
- else {
- (usage.constructs || (usage.constructs = [])).push(call);
- }
- }
- function inferTypeFromPropertyAccessExpression(parent, usage) {
- var name = ts.escapeLeadingUnderscores(parent.name.text);
- if (!usage.properties) {
- usage.properties = ts.createUnderscoreEscapedMap();
- }
- var propertyUsage = usage.properties.get(name) || createEmptyUsage();
- calculateUsageOfNode(parent, propertyUsage);
- usage.properties.set(name, propertyUsage);
- }
- function inferTypeFromPropertyElementExpression(parent, node, usage) {
- if (node === parent.argumentExpression) {
- usage.isNumberOrString = true;
- return;
- }
- else {
- var indexType = checker.getTypeAtLocation(parent.argumentExpression);
- var indexUsage = createEmptyUsage();
- calculateUsageOfNode(parent, indexUsage);
- if (indexType.flags & 296 /* NumberLike */) {
- usage.numberIndex = indexUsage;
- }
- else {
- usage.stringIndex = indexUsage;
- }
- }
- }
- function inferTypeFromPropertyAssignment(assignment, usage) {
- var nodeWithRealType = ts.isVariableDeclaration(assignment.parent.parent) ?
- assignment.parent.parent :
- assignment.parent;
- addCandidateThisType(usage, checker.getTypeAtLocation(nodeWithRealType));
- }
- function inferTypeFromPropertyDeclaration(declaration, usage) {
- addCandidateThisType(usage, checker.getTypeAtLocation(declaration.parent));
- }
- function removeLowPriorityInferences(inferences, priorities) {
- var toRemove = [];
- for (var _i = 0, inferences_1 = inferences; _i < inferences_1.length; _i++) {
- var i = inferences_1[_i];
- for (var _a = 0, priorities_1 = priorities; _a < priorities_1.length; _a++) {
- var _b = priorities_1[_a], high = _b.high, low = _b.low;
- if (high(i)) {
- ts.Debug.assert(!low(i), "Priority can't have both low and high");
- toRemove.push(low);
- }
- }
- }
- return inferences.filter(function (i) { return toRemove.every(function (f) { return !f(i); }); });
- }
- function combineFromUsage(usage) {
- return combineTypes(inferTypes(usage));
- }
- function combineTypes(inferences) {
- if (!inferences.length)
- return checker.getAnyType();
- // 1. string or number individually override string | number
- // 2. non-any, non-void overrides any or void
- // 3. non-nullable, non-any, non-void, non-anonymous overrides anonymous types
- var stringNumber = checker.getUnionType([checker.getStringType(), checker.getNumberType()]);
- var priorities = [
- {
- high: function (t) { return t === checker.getStringType() || t === checker.getNumberType(); },
- low: function (t) { return t === stringNumber; }
- },
- {
- high: function (t) { return !(t.flags & (1 /* Any */ | 16384 /* Void */)); },
- low: function (t) { return !!(t.flags & (1 /* Any */ | 16384 /* Void */)); }
- },
- {
- high: function (t) { return !(t.flags & (98304 /* Nullable */ | 1 /* Any */ | 16384 /* Void */)) && !(ts.getObjectFlags(t) & 16 /* Anonymous */); },
- low: function (t) { return !!(ts.getObjectFlags(t) & 16 /* Anonymous */); }
- }
- ];
- var good = removeLowPriorityInferences(inferences, priorities);
- var anons = good.filter(function (i) { return ts.getObjectFlags(i) & 16 /* Anonymous */; });
- if (anons.length) {
- good = good.filter(function (i) { return !(ts.getObjectFlags(i) & 16 /* Anonymous */); });
- good.push(combineAnonymousTypes(anons));
- }
- return checker.getWidenedType(checker.getUnionType(good.map(checker.getBaseTypeOfLiteralType), 2 /* Subtype */));
- }
- function combineAnonymousTypes(anons) {
- if (anons.length === 1) {
- return anons[0];
- }
- var calls = [];
- var constructs = [];
- var stringIndices = [];
- var numberIndices = [];
- var stringIndexReadonly = false;
- var numberIndexReadonly = false;
- var props = ts.createMultiMap();
- for (var _i = 0, anons_1 = anons; _i < anons_1.length; _i++) {
- var anon = anons_1[_i];
- for (var _a = 0, _b = checker.getPropertiesOfType(anon); _a < _b.length; _a++) {
- var p = _b[_a];
- props.add(p.name, checker.getTypeOfSymbolAtLocation(p, p.valueDeclaration));
- }
- calls.push.apply(calls, checker.getSignaturesOfType(anon, 0 /* Call */));
- constructs.push.apply(constructs, checker.getSignaturesOfType(anon, 1 /* Construct */));
- if (anon.stringIndexInfo) {
- stringIndices.push(anon.stringIndexInfo.type);
- stringIndexReadonly = stringIndexReadonly || anon.stringIndexInfo.isReadonly;
- }
- if (anon.numberIndexInfo) {
- numberIndices.push(anon.numberIndexInfo.type);
- numberIndexReadonly = numberIndexReadonly || anon.numberIndexInfo.isReadonly;
- }
- }
- var members = ts.mapEntries(props, function (name, types) {
- var isOptional = types.length < anons.length ? 16777216 /* Optional */ : 0;
- var s = checker.createSymbol(4 /* Property */ | isOptional, name);
- s.type = checker.getUnionType(types);
- return [name, s];
- });
- return checker.createAnonymousType(anons[0].symbol, members, calls, constructs, stringIndices.length ? checker.createIndexInfo(checker.getUnionType(stringIndices), stringIndexReadonly) : undefined, numberIndices.length ? checker.createIndexInfo(checker.getUnionType(numberIndices), numberIndexReadonly) : undefined);
- }
- function inferTypes(usage) {
- var _a, _b, _c;
- var types = [];
- if (usage.isNumber) {
- types.push(checker.getNumberType());
- }
- if (usage.isString) {
- types.push(checker.getStringType());
- }
- if (usage.isNumberOrString) {
- types.push(checker.getUnionType([checker.getStringType(), checker.getNumberType()]));
- }
- if (usage.numberIndex) {
- types.push(checker.createArrayType(combineFromUsage(usage.numberIndex)));
- }
- if (((_a = usage.properties) === null || _a === void 0 ? void 0 : _a.size) || ((_b = usage.calls) === null || _b === void 0 ? void 0 : _b.length) || ((_c = usage.constructs) === null || _c === void 0 ? void 0 : _c.length) || usage.stringIndex) {
- types.push(inferStructuralType(usage));
- }
- types.push.apply(types, (usage.candidateTypes || []).map(function (t) { return checker.getBaseTypeOfLiteralType(t); }));
- types.push.apply(types, inferNamedTypesFromProperties(usage));
- return types;
- }
- function inferStructuralType(usage) {
- var members = ts.createUnderscoreEscapedMap();
- if (usage.properties) {
- usage.properties.forEach(function (u, name) {
- var symbol = checker.createSymbol(4 /* Property */, name);
- symbol.type = combineFromUsage(u);
- members.set(name, symbol);
- });
- }
- var callSignatures = usage.calls ? [getSignatureFromCalls(usage.calls)] : [];
- var constructSignatures = usage.constructs ? [getSignatureFromCalls(usage.constructs)] : [];
- var stringIndexInfo = usage.stringIndex && checker.createIndexInfo(combineFromUsage(usage.stringIndex), /*isReadonly*/ false);
- return checker.createAnonymousType(/*symbol*/ undefined, members, callSignatures, constructSignatures, stringIndexInfo, /*numberIndexInfo*/ undefined);
- }
- function inferNamedTypesFromProperties(usage) {
- if (!usage.properties || !usage.properties.size)
- return [];
- var types = builtins.filter(function (t) { return allPropertiesAreAssignableToUsage(t, usage); });
- if (0 < types.length && types.length < 3) {
- return types.map(function (t) { return inferInstantiationFromUsage(t, usage); });
- }
- return [];
- }
- function allPropertiesAreAssignableToUsage(type, usage) {
- if (!usage.properties)
- return false;
- return !ts.forEachEntry(usage.properties, function (propUsage, name) {
- var source = checker.getTypeOfPropertyOfType(type, name);
- if (!source) {
- return true;
- }
- if (propUsage.calls) {
- var sigs = checker.getSignaturesOfType(source, 0 /* Call */);
- return !sigs.length || !checker.isTypeAssignableTo(source, getFunctionFromCalls(propUsage.calls));
- }
- else {
- return !checker.isTypeAssignableTo(source, combineFromUsage(propUsage));
- }
- });
- }
- /**
- * inference is limited to
- * 1. generic types with a single parameter
- * 2. inference to/from calls with a single signature
- */
- function inferInstantiationFromUsage(type, usage) {
- if (!(ts.getObjectFlags(type) & 4 /* Reference */) || !usage.properties) {
- return type;
- }
- var generic = type.target;
- var singleTypeParameter = ts.singleOrUndefined(generic.typeParameters);
- if (!singleTypeParameter)
- return type;
- var types = [];
- usage.properties.forEach(function (propUsage, name) {
- var genericPropertyType = checker.getTypeOfPropertyOfType(generic, name);
- ts.Debug.assert(!!genericPropertyType, "generic should have all the properties of its reference.");
- types.push.apply(types, inferTypeParameters(genericPropertyType, combineFromUsage(propUsage), singleTypeParameter));
- });
- return builtinConstructors[type.symbol.escapedName](combineTypes(types));
- }
- function inferTypeParameters(genericType, usageType, typeParameter) {
- if (genericType === typeParameter) {
- return [usageType];
- }
- else if (genericType.flags & 3145728 /* UnionOrIntersection */) {
- return ts.flatMap(genericType.types, function (t) { return inferTypeParameters(t, usageType, typeParameter); });
- }
- else if (ts.getObjectFlags(genericType) & 4 /* Reference */ && ts.getObjectFlags(usageType) & 4 /* Reference */) {
- // this is wrong because we need a reference to the targetType to, so we can check that it's also a reference
- var genericArgs = checker.getTypeArguments(genericType);
- var usageArgs = checker.getTypeArguments(usageType);
- var types = [];
- if (genericArgs && usageArgs) {
- for (var i = 0; i < genericArgs.length; i++) {
- if (usageArgs[i]) {
- types.push.apply(types, inferTypeParameters(genericArgs[i], usageArgs[i], typeParameter));
- }
- }
- }
- return types;
- }
- var genericSigs = checker.getSignaturesOfType(genericType, 0 /* Call */);
- var usageSigs = checker.getSignaturesOfType(usageType, 0 /* Call */);
- if (genericSigs.length === 1 && usageSigs.length === 1) {
- return inferFromSignatures(genericSigs[0], usageSigs[0], typeParameter);
- }
- return [];
- }
- function inferFromSignatures(genericSig, usageSig, typeParameter) {
- var types = [];
- for (var i = 0; i < genericSig.parameters.length; i++) {
- var genericParam = genericSig.parameters[i];
- var usageParam = usageSig.parameters[i];
- var isRest = genericSig.declaration && ts.isRestParameter(genericSig.declaration.parameters[i]);
- if (!usageParam) {
- break;
- }
- var genericParamType = checker.getTypeOfSymbolAtLocation(genericParam, genericParam.valueDeclaration);
- var elementType = isRest && checker.getElementTypeOfArrayType(genericParamType);
- if (elementType) {
- genericParamType = elementType;
- }
- var targetType = usageParam.type || checker.getTypeOfSymbolAtLocation(usageParam, usageParam.valueDeclaration);
- types.push.apply(types, inferTypeParameters(genericParamType, targetType, typeParameter));
- }
- var genericReturn = checker.getReturnTypeOfSignature(genericSig);
- var usageReturn = checker.getReturnTypeOfSignature(usageSig);
- types.push.apply(types, inferTypeParameters(genericReturn, usageReturn, typeParameter));
- return types;
- }
- function getFunctionFromCalls(calls) {
- return checker.createAnonymousType(/*symbol*/ undefined, ts.createSymbolTable(), [getSignatureFromCalls(calls)], ts.emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
- }
- function getSignatureFromCalls(calls) {
- var parameters = [];
- var length = Math.max.apply(Math, calls.map(function (c) { return c.argumentTypes.length; }));
- var _loop_14 = function (i) {
- var symbol = checker.createSymbol(1 /* FunctionScopedVariable */, ts.escapeLeadingUnderscores("arg" + i));
- symbol.type = combineTypes(calls.map(function (call) { return call.argumentTypes[i] || checker.getUndefinedType(); }));
- if (calls.some(function (call) { return call.argumentTypes[i] === undefined; })) {
- symbol.flags |= 16777216 /* Optional */;
- }
- parameters.push(symbol);
- };
- for (var i = 0; i < length; i++) {
- _loop_14(i);
- }
- var returnType = combineFromUsage(combineUsages(calls.map(function (call) { return call.return_; })));
- // TODO: GH#18217
- return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, length, 0 /* None */);
- }
- function addCandidateType(usage, type) {
- if (type && !(type.flags & 1 /* Any */) && !(type.flags & 131072 /* Never */)) {
- (usage.candidateTypes || (usage.candidateTypes = [])).push(type);
- }
- }
- function addCandidateThisType(usage, type) {
- if (type && !(type.flags & 1 /* Any */) && !(type.flags & 131072 /* Never */)) {
- (usage.candidateThisTypes || (usage.candidateThisTypes = [])).push(type);
- }
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixName = "disableJsDiagnostics";
- var fixId = "disableJsDiagnostics";
- var errorCodes = ts.mapDefined(Object.keys(ts.Diagnostics), function (key) {
- var diag = ts.Diagnostics[key];
- return diag.category === ts.DiagnosticCategory.Error ? diag.code : undefined;
- });
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, span = context.span, host = context.host, formatContext = context.formatContext;
- if (!ts.isInJSFile(sourceFile) || !ts.isCheckJsEnabledForFile(sourceFile, program.getCompilerOptions())) {
- return undefined;
- }
- var newLineCharacter = sourceFile.checkJsDirective ? "" : ts.getNewLineOrDefaultFromHost(host, formatContext.options);
- var fixes = [
- // fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file.
- codefix.createCodeFixActionWithoutFixAll(fixName, [codefix.createFileTextChanges(sourceFile.fileName, [
- ts.createTextChange(sourceFile.checkJsDirective
- ? ts.createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end)
- : ts.createTextSpan(0, 0), "// @ts-nocheck" + newLineCharacter),
- ])], ts.Diagnostics.Disable_checking_for_this_file),
- ];
- if (ts.textChanges.isValidLocationToAddComment(sourceFile, span.start)) {
- fixes.unshift(codefix.createCodeFixAction(fixName, ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, sourceFile, span.start); }), ts.Diagnostics.Ignore_this_error_message, fixId, ts.Diagnostics.Add_ts_ignore_to_all_error_messages));
- }
- return fixes;
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var seenLines = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- if (ts.textChanges.isValidLocationToAddComment(diag.file, diag.start)) {
- makeChange(changes, diag.file, diag.start, seenLines);
- }
- });
- },
- });
- function makeChange(changes, sourceFile, position, seenLines) {
- var lineNumber = ts.getLineAndCharacterOfPosition(sourceFile, position).line;
- // Only need to add `// @ts-ignore` for a line once.
- if (!seenLines || ts.addToSeen(seenLines, lineNumber)) {
- changes.insertCommentBeforeLine(sourceFile, lineNumber, position, " @ts-ignore");
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- /**
- * Finds members of the resolved type that are missing in the class pointed to by class decl
- * and generates source code for the missing members.
- * @param possiblyMissingSymbols The collection of symbols to filter and then get insertions for.
- * @param importAdder If provided, type annotations will use identifier type references instead of ImportTypeNodes, and the missing imports will be added to the importAdder.
- * @returns Empty string iff there are no member insertions.
- */
- function createMissingMemberNodes(classDeclaration, possiblyMissingSymbols, context, preferences, importAdder, addClassElement) {
- var classMembers = classDeclaration.symbol.members;
- for (var _i = 0, possiblyMissingSymbols_1 = possiblyMissingSymbols; _i < possiblyMissingSymbols_1.length; _i++) {
- var symbol = possiblyMissingSymbols_1[_i];
- if (!classMembers.has(symbol.escapedName)) {
- addNewNodeForMemberSymbol(symbol, classDeclaration, context, preferences, importAdder, addClassElement);
- }
- }
- }
- codefix.createMissingMemberNodes = createMissingMemberNodes;
- function getNoopSymbolTrackerWithResolver(context) {
- return {
- trackSymbol: ts.noop,
- moduleResolverHost: ts.getModuleSpecifierResolverHost(context.program, context.host),
- };
- }
- codefix.getNoopSymbolTrackerWithResolver = getNoopSymbolTrackerWithResolver;
- /**
- * @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`.
- */
- function addNewNodeForMemberSymbol(symbol, enclosingDeclaration, context, preferences, importAdder, addClassElement) {
- var declarations = symbol.getDeclarations();
- if (!(declarations && declarations.length)) {
- return undefined;
- }
- var checker = context.program.getTypeChecker();
- var scriptTarget = ts.getEmitScriptTarget(context.program.getCompilerOptions());
- var declaration = declarations[0];
- var name = ts.getSynthesizedDeepClone(ts.getNameOfDeclaration(declaration), /*includeTrivia*/ false);
- var visibilityModifier = createVisibilityModifier(ts.getModifierFlags(declaration));
- var modifiers = visibilityModifier ? ts.createNodeArray([visibilityModifier]) : undefined;
- var type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration));
- var optional = !!(symbol.flags & 16777216 /* Optional */);
- var ambient = !!(enclosingDeclaration.flags & 8388608 /* Ambient */);
- switch (declaration.kind) {
- case 158 /* PropertySignature */:
- case 159 /* PropertyDeclaration */:
- var flags = preferences.quotePreference === "single" ? 268435456 /* UseSingleQuotesForStringLiteralType */ : undefined;
- var typeNode = checker.typeToTypeNode(type, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context));
- if (importAdder) {
- var importableReference = tryGetAutoImportableReferenceFromImportTypeNode(typeNode, type, scriptTarget);
- if (importableReference) {
- typeNode = importableReference.typeReference;
- importSymbols(importAdder, importableReference.symbols);
- }
- }
- addClassElement(ts.createProperty(
- /*decorators*/ undefined, modifiers, name, optional ? ts.createToken(57 /* QuestionToken */) : undefined, typeNode,
- /*initializer*/ undefined));
- break;
- case 163 /* GetAccessor */:
- case 164 /* SetAccessor */: {
- var typeNode_1 = checker.typeToTypeNode(type, enclosingDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context));
- var allAccessors = ts.getAllAccessorDeclarations(declarations, declaration);
- var orderedAccessors = allAccessors.secondAccessor
- ? [allAccessors.firstAccessor, allAccessors.secondAccessor]
- : [allAccessors.firstAccessor];
- if (importAdder) {
- var importableReference = tryGetAutoImportableReferenceFromImportTypeNode(typeNode_1, type, scriptTarget);
- if (importableReference) {
- typeNode_1 = importableReference.typeReference;
- importSymbols(importAdder, importableReference.symbols);
- }
- }
- for (var _i = 0, orderedAccessors_1 = orderedAccessors; _i < orderedAccessors_1.length; _i++) {
- var accessor = orderedAccessors_1[_i];
- if (ts.isGetAccessorDeclaration(accessor)) {
- addClassElement(ts.createGetAccessor(
- /*decorators*/ undefined, modifiers, name, ts.emptyArray, typeNode_1, ambient ? undefined : createStubbedMethodBody(preferences)));
- }
- else {
- ts.Debug.assertNode(accessor, ts.isSetAccessorDeclaration, "The counterpart to a getter should be a setter");
- var parameter = ts.getSetAccessorValueParameter(accessor);
- var parameterName = parameter && ts.isIdentifier(parameter.name) ? ts.idText(parameter.name) : undefined;
- addClassElement(ts.createSetAccessor(
- /*decorators*/ undefined, modifiers, name, createDummyParameters(1, [parameterName], [typeNode_1], 1, /*inJs*/ false), ambient ? undefined : createStubbedMethodBody(preferences)));
- }
- }
- break;
- }
- case 160 /* MethodSignature */:
- case 161 /* MethodDeclaration */:
- // The signature for the implementation appears as an entry in `signatures` iff
- // there is only one signature.
- // If there are overloads and an implementation signature, it appears as an
- // extra declaration that isn't a signature for `type`.
- // If there is more than one overload but no implementation signature
- // (eg: an abstract method or interface declaration), there is a 1-1
- // correspondence of declarations and signatures.
- var signatures = checker.getSignaturesOfType(type, 0 /* Call */);
- if (!ts.some(signatures)) {
- break;
- }
- if (declarations.length === 1) {
- ts.Debug.assert(signatures.length === 1, "One declaration implies one signature");
- var signature = signatures[0];
- outputMethod(signature, modifiers, name, ambient ? undefined : createStubbedMethodBody(preferences));
- break;
- }
- for (var _a = 0, signatures_1 = signatures; _a < signatures_1.length; _a++) {
- var signature = signatures_1[_a];
- // Need to ensure nodes are fresh each time so they can have different positions.
- outputMethod(signature, ts.getSynthesizedDeepClones(modifiers, /*includeTrivia*/ false), ts.getSynthesizedDeepClone(name, /*includeTrivia*/ false));
- }
- if (!ambient) {
- if (declarations.length > signatures.length) {
- var signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1]);
- outputMethod(signature, modifiers, name, createStubbedMethodBody(preferences));
- }
- else {
- ts.Debug.assert(declarations.length === signatures.length, "Declarations and signatures should match count");
- addClassElement(createMethodImplementingSignatures(signatures, name, optional, modifiers, preferences));
- }
- }
- break;
- }
- function outputMethod(signature, modifiers, name, body) {
- var method = signatureToMethodDeclaration(context, signature, enclosingDeclaration, modifiers, name, optional, body, importAdder);
- if (method)
- addClassElement(method);
- }
- }
- function signatureToMethodDeclaration(context, signature, enclosingDeclaration, modifiers, name, optional, body, importAdder) {
- var program = context.program;
- var checker = program.getTypeChecker();
- var scriptTarget = ts.getEmitScriptTarget(program.getCompilerOptions());
- var signatureDeclaration = checker.signatureToSignatureDeclaration(signature, 161 /* MethodDeclaration */, enclosingDeclaration, 1 /* NoTruncation */ | 256 /* SuppressAnyReturnType */, getNoopSymbolTrackerWithResolver(context));
- if (!signatureDeclaration) {
- return undefined;
- }
- if (importAdder) {
- if (signatureDeclaration.typeParameters) {
- ts.forEach(signatureDeclaration.typeParameters, function (typeParameterDecl, i) {
- var typeParameter = signature.typeParameters[i];
- if (typeParameterDecl.constraint) {
- var importableReference = tryGetAutoImportableReferenceFromImportTypeNode(typeParameterDecl.constraint, typeParameter.constraint, scriptTarget);
- if (importableReference) {
- typeParameterDecl.constraint = importableReference.typeReference;
- importSymbols(importAdder, importableReference.symbols);
- }
- }
- if (typeParameterDecl.default) {
- var importableReference = tryGetAutoImportableReferenceFromImportTypeNode(typeParameterDecl.default, typeParameter.default, scriptTarget);
- if (importableReference) {
- typeParameterDecl.default = importableReference.typeReference;
- importSymbols(importAdder, importableReference.symbols);
- }
- }
- });
- }
- ts.forEach(signatureDeclaration.parameters, function (parameterDecl, i) {
- var parameter = signature.parameters[i];
- var importableReference = tryGetAutoImportableReferenceFromImportTypeNode(parameterDecl.type, checker.getTypeAtLocation(parameter.valueDeclaration), scriptTarget);
- if (importableReference) {
- parameterDecl.type = importableReference.typeReference;
- importSymbols(importAdder, importableReference.symbols);
- }
- });
- if (signatureDeclaration.type) {
- var importableReference = tryGetAutoImportableReferenceFromImportTypeNode(signatureDeclaration.type, signature.resolvedReturnType, scriptTarget);
- if (importableReference) {
- signatureDeclaration.type = importableReference.typeReference;
- importSymbols(importAdder, importableReference.symbols);
- }
- }
- }
- signatureDeclaration.decorators = undefined;
- signatureDeclaration.modifiers = modifiers;
- signatureDeclaration.name = name;
- signatureDeclaration.questionToken = optional ? ts.createToken(57 /* QuestionToken */) : undefined;
- signatureDeclaration.body = body;
- return signatureDeclaration;
- }
- function createMethodFromCallExpression(context, call, methodName, inJs, makeStatic, contextNode, importAdder) {
- var body = !ts.isInterfaceDeclaration(contextNode);
- var typeArguments = call.typeArguments, args = call.arguments, parent = call.parent;
- var scriptTarget = ts.getEmitScriptTarget(context.program.getCompilerOptions());
- var checker = context.program.getTypeChecker();
- var tracker = getNoopSymbolTrackerWithResolver(context);
- var types = ts.map(args, function (arg) {
- return typeToAutoImportableTypeNode(checker, importAdder, checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(arg)), contextNode, scriptTarget, /*flags*/ undefined, tracker);
- });
- var names = ts.map(args, function (arg) {
- return ts.isIdentifier(arg) ? arg.text : ts.isPropertyAccessExpression(arg) && ts.isIdentifier(arg.name) ? arg.name.text : undefined;
- });
- var contextualType = checker.getContextualType(call);
- var returnType = (inJs || !contextualType) ? undefined : checker.typeToTypeNode(contextualType, contextNode, /*flags*/ undefined, tracker);
- return ts.createMethod(
- /*decorators*/ undefined,
- /*modifiers*/ makeStatic ? [ts.createToken(120 /* StaticKeyword */)] : undefined,
- /*asteriskToken*/ ts.isYieldExpression(parent) ? ts.createToken(41 /* AsteriskToken */) : undefined, methodName,
- /*questionToken*/ undefined,
- /*typeParameters*/ inJs ? undefined : ts.map(typeArguments, function (_, i) {
- return ts.createTypeParameterDeclaration(84 /* T */ + typeArguments.length - 1 <= 90 /* Z */ ? String.fromCharCode(84 /* T */ + i) : "T" + i);
- }),
- /*parameters*/ createDummyParameters(args.length, names, types, /*minArgumentCount*/ undefined, inJs),
- /*type*/ returnType, body ? createStubbedMethodBody(context.preferences) : undefined);
- }
- codefix.createMethodFromCallExpression = createMethodFromCallExpression;
- function typeToAutoImportableTypeNode(checker, importAdder, type, contextNode, scriptTarget, flags, tracker) {
- var typeNode = checker.typeToTypeNode(type, contextNode, flags, tracker);
- if (typeNode && ts.isImportTypeNode(typeNode)) {
- var importableReference = tryGetAutoImportableReferenceFromImportTypeNode(typeNode, type, scriptTarget);
- if (importableReference) {
- importSymbols(importAdder, importableReference.symbols);
- return importableReference.typeReference;
- }
- }
- return typeNode;
- }
- codefix.typeToAutoImportableTypeNode = typeToAutoImportableTypeNode;
- function createDummyParameters(argCount, names, types, minArgumentCount, inJs) {
- var parameters = [];
- for (var i = 0; i < argCount; i++) {
- var newParameter = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- /*dotDotDotToken*/ undefined,
- /*name*/ names && names[i] || "arg" + i,
- /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? ts.createToken(57 /* QuestionToken */) : undefined,
- /*type*/ inJs ? undefined : types && types[i] || ts.createKeywordTypeNode(125 /* AnyKeyword */),
- /*initializer*/ undefined);
- parameters.push(newParameter);
- }
- return parameters;
- }
- function createMethodImplementingSignatures(signatures, name, optional, modifiers, preferences) {
- /** This is *a* signature with the maximal number of arguments,
- * such that if there is a "maximal" signature without rest arguments,
- * this is one of them.
- */
- var maxArgsSignature = signatures[0];
- var minArgumentCount = signatures[0].minArgumentCount;
- var someSigHasRestParameter = false;
- for (var _i = 0, signatures_2 = signatures; _i < signatures_2.length; _i++) {
- var sig = signatures_2[_i];
- minArgumentCount = Math.min(sig.minArgumentCount, minArgumentCount);
- if (ts.signatureHasRestParameter(sig)) {
- someSigHasRestParameter = true;
- }
- if (sig.parameters.length >= maxArgsSignature.parameters.length && (!ts.signatureHasRestParameter(sig) || ts.signatureHasRestParameter(maxArgsSignature))) {
- maxArgsSignature = sig;
- }
- }
- var maxNonRestArgs = maxArgsSignature.parameters.length - (ts.signatureHasRestParameter(maxArgsSignature) ? 1 : 0);
- var maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(function (symbol) { return symbol.name; });
- var parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, /* types */ undefined, minArgumentCount, /*inJs*/ false);
- if (someSigHasRestParameter) {
- var anyArrayType = ts.createArrayTypeNode(ts.createKeywordTypeNode(125 /* AnyKeyword */));
- var restParameter = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.createToken(25 /* DotDotDotToken */), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest",
- /*questionToken*/ maxNonRestArgs >= minArgumentCount ? ts.createToken(57 /* QuestionToken */) : undefined, anyArrayType,
- /*initializer*/ undefined);
- parameters.push(restParameter);
- }
- return createStubbedMethod(modifiers, name, optional,
- /*typeParameters*/ undefined, parameters,
- /*returnType*/ undefined, preferences);
- }
- function createStubbedMethod(modifiers, name, optional, typeParameters, parameters, returnType, preferences) {
- return ts.createMethod(
- /*decorators*/ undefined, modifiers,
- /*asteriskToken*/ undefined, name, optional ? ts.createToken(57 /* QuestionToken */) : undefined, typeParameters, parameters, returnType, createStubbedMethodBody(preferences));
- }
- function createStubbedMethodBody(preferences) {
- return ts.createBlock([ts.createThrow(ts.createNew(ts.createIdentifier("Error"),
- /*typeArguments*/ undefined,
- // TODO Handle auto quote preference.
- [ts.createLiteral("Method not implemented.", /*isSingleQuote*/ preferences.quotePreference === "single")]))],
- /*multiline*/ true);
- }
- function createVisibilityModifier(flags) {
- if (flags & 4 /* Public */) {
- return ts.createToken(119 /* PublicKeyword */);
- }
- else if (flags & 16 /* Protected */) {
- return ts.createToken(118 /* ProtectedKeyword */);
- }
- return undefined;
- }
- function setJsonCompilerOptionValues(changeTracker, configFile, options) {
- var tsconfigObjectLiteral = ts.getTsConfigObjectLiteralExpression(configFile);
- if (!tsconfigObjectLiteral)
- return undefined;
- var compilerOptionsProperty = findJsonProperty(tsconfigObjectLiteral, "compilerOptions");
- if (compilerOptionsProperty === undefined) {
- changeTracker.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment("compilerOptions", ts.createObjectLiteral(options.map(function (_a) {
- var optionName = _a[0], optionValue = _a[1];
- return createJsonPropertyAssignment(optionName, optionValue);
- }), /*multiLine*/ true)));
- return;
- }
- var compilerOptions = compilerOptionsProperty.initializer;
- if (!ts.isObjectLiteralExpression(compilerOptions)) {
- return;
- }
- for (var _i = 0, options_1 = options; _i < options_1.length; _i++) {
- var _a = options_1[_i], optionName = _a[0], optionValue = _a[1];
- var optionProperty = findJsonProperty(compilerOptions, optionName);
- if (optionProperty === undefined) {
- changeTracker.insertNodeAtObjectStart(configFile, compilerOptions, createJsonPropertyAssignment(optionName, optionValue));
- }
- else {
- changeTracker.replaceNode(configFile, optionProperty.initializer, optionValue);
- }
- }
- }
- codefix.setJsonCompilerOptionValues = setJsonCompilerOptionValues;
- function setJsonCompilerOptionValue(changeTracker, configFile, optionName, optionValue) {
- setJsonCompilerOptionValues(changeTracker, configFile, [[optionName, optionValue]]);
- }
- codefix.setJsonCompilerOptionValue = setJsonCompilerOptionValue;
- function createJsonPropertyAssignment(name, initializer) {
- return ts.createPropertyAssignment(ts.createStringLiteral(name), initializer);
- }
- codefix.createJsonPropertyAssignment = createJsonPropertyAssignment;
- function findJsonProperty(obj, name) {
- return ts.find(obj.properties, function (p) { return ts.isPropertyAssignment(p) && !!p.name && ts.isStringLiteral(p.name) && p.name.text === name; });
- }
- codefix.findJsonProperty = findJsonProperty;
- /**
- * Given an ImportTypeNode 'import("./a").SomeType>',
- * returns an equivalent type reference node with any nested ImportTypeNodes also replaced
- * with type references, and a list of symbols that must be imported to use the type reference.
- */
- function tryGetAutoImportableReferenceFromImportTypeNode(importTypeNode, type, scriptTarget) {
- if (importTypeNode && ts.isLiteralImportTypeNode(importTypeNode) && importTypeNode.qualifier && (!type || type.symbol)) {
- // Symbol for the left-most thing after the dot
- var firstIdentifier = ts.getFirstIdentifier(importTypeNode.qualifier);
- var name = ts.getNameForExportedSymbol(firstIdentifier.symbol, scriptTarget);
- var qualifier = name !== firstIdentifier.text
- ? replaceFirstIdentifierOfEntityName(importTypeNode.qualifier, ts.createIdentifier(name))
- : importTypeNode.qualifier;
- var symbols_4 = [firstIdentifier.symbol];
- var typeArguments_1 = [];
- if (importTypeNode.typeArguments) {
- importTypeNode.typeArguments.forEach(function (arg) {
- var ref = tryGetAutoImportableReferenceFromImportTypeNode(arg, /*undefined*/ type, scriptTarget);
- if (ref) {
- symbols_4.push.apply(symbols_4, ref.symbols);
- typeArguments_1.push(ref.typeReference);
- }
- else {
- typeArguments_1.push(arg);
- }
- });
- }
- return {
- symbols: symbols_4,
- typeReference: ts.createTypeReferenceNode(qualifier, typeArguments_1)
- };
- }
- }
- codefix.tryGetAutoImportableReferenceFromImportTypeNode = tryGetAutoImportableReferenceFromImportTypeNode;
- function replaceFirstIdentifierOfEntityName(name, newIdentifier) {
- if (name.kind === 75 /* Identifier */) {
- return newIdentifier;
- }
- return ts.createQualifiedName(replaceFirstIdentifierOfEntityName(name.left, newIdentifier), name.right);
- }
- function importSymbols(importAdder, symbols) {
- symbols.forEach(function (s) { return importAdder.addImportFromExportedSymbol(s, /*usageIsTypeOnly*/ true); });
- }
- codefix.importSymbols = importSymbols;
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixName = "invalidImportSyntax";
- function getCodeFixesForImportDeclaration(context, node) {
- var sourceFile = ts.getSourceFileOfNode(node);
- var namespace = ts.getNamespaceDeclarationNode(node);
- var opts = context.program.getCompilerOptions();
- var variations = [];
- // import Bluebird from "bluebird";
- variations.push(createAction(context, sourceFile, node, ts.makeImport(namespace.name, /*namedImports*/ undefined, node.moduleSpecifier, ts.getQuotePreference(sourceFile, context.preferences))));
- if (ts.getEmitModuleKind(opts) === ts.ModuleKind.CommonJS) {
- // import Bluebird = require("bluebird");
- variations.push(createAction(context, sourceFile, node, ts.createImportEqualsDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, namespace.name, ts.createExternalModuleReference(node.moduleSpecifier))));
- }
- return variations;
- }
- function createAction(context, sourceFile, node, replacement) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile, node, replacement); });
- return codefix.createCodeFixActionWithoutFixAll(fixName, changes, [ts.Diagnostics.Replace_import_with_0, changes[0].textChanges[0].newText]);
- }
- codefix.registerCodeFix({
- errorCodes: [
- ts.Diagnostics.This_expression_is_not_callable.code,
- ts.Diagnostics.This_expression_is_not_constructable.code,
- ],
- getCodeActions: getActionsForUsageOfInvalidImport
- });
- function getActionsForUsageOfInvalidImport(context) {
- var sourceFile = context.sourceFile;
- var targetKind = ts.Diagnostics.This_expression_is_not_callable.code === context.errorCode ? 196 /* CallExpression */ : 197 /* NewExpression */;
- var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start), function (a) { return a.kind === targetKind; });
- if (!node) {
- return [];
- }
- var expr = node.expression;
- return getImportCodeFixesForExpression(context, expr);
- }
- codefix.registerCodeFix({
- errorCodes: [
- // The following error codes cover pretty much all assignability errors that could involve an expression
- ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code,
- ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1.code,
- ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code,
- ts.Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated.code,
- ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1.code,
- ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_string_index_type_2.code,
- ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_numeric_index_type_2.code,
- ts.Diagnostics.Numeric_index_type_0_is_not_assignable_to_string_index_type_1.code,
- ts.Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2.code,
- ts.Diagnostics.Property_0_in_type_1_is_not_assignable_to_type_2.code,
- ts.Diagnostics.Property_0_of_JSX_spread_attribute_is_not_assignable_to_target_property.code,
- ts.Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1.code,
- ],
- getCodeActions: getActionsForInvalidImportLocation
- });
- function getActionsForInvalidImportLocation(context) {
- var sourceFile = context.sourceFile;
- var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start), function (a) { return a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); });
- if (!node) {
- return [];
- }
- return getImportCodeFixesForExpression(context, node);
- }
- function getImportCodeFixesForExpression(context, expr) {
- var type = context.program.getTypeChecker().getTypeAtLocation(expr);
- if (!(type.symbol && type.symbol.originatingImport)) {
- return [];
- }
- var fixes = [];
- var relatedImport = type.symbol.originatingImport; // TODO: GH#18217
- if (!ts.isImportCall(relatedImport)) {
- ts.addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport));
- }
- if (ts.isExpression(expr) && !(ts.isNamedDeclaration(expr.parent) && expr.parent.name === expr)) {
- var sourceFile_1 = context.sourceFile;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile_1, expr, ts.createPropertyAccess(expr, "default"), {}); });
- fixes.push(codefix.createCodeFixActionWithoutFixAll(fixName, changes, ts.Diagnostics.Use_synthetic_default_member));
- }
- return fixes;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixName = "strictClassInitialization";
- var fixIdAddDefiniteAssignmentAssertions = "addMissingPropertyDefiniteAssignmentAssertions";
- var fixIdAddUndefinedType = "addMissingPropertyUndefinedType";
- var fixIdAddInitializer = "addMissingPropertyInitializer";
- var errorCodes = [ts.Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var propertyDeclaration = getPropertyDeclaration(context.sourceFile, context.span.start);
- if (!propertyDeclaration)
- return;
- var result = [
- getActionForAddMissingUndefinedType(context, propertyDeclaration),
- getActionForAddMissingDefiniteAssignmentAssertion(context, propertyDeclaration)
- ];
- ts.append(result, getActionForAddMissingInitializer(context, propertyDeclaration));
- return result;
- },
- fixIds: [fixIdAddDefiniteAssignmentAssertions, fixIdAddUndefinedType, fixIdAddInitializer],
- getAllCodeActions: function (context) {
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var propertyDeclaration = getPropertyDeclaration(diag.file, diag.start);
- if (!propertyDeclaration)
- return;
- switch (context.fixId) {
- case fixIdAddDefiniteAssignmentAssertions:
- addDefiniteAssignmentAssertion(changes, diag.file, propertyDeclaration);
- break;
- case fixIdAddUndefinedType:
- addUndefinedType(changes, diag.file, propertyDeclaration);
- break;
- case fixIdAddInitializer:
- var checker = context.program.getTypeChecker();
- var initializer = getInitializer(checker, propertyDeclaration);
- if (!initializer)
- return;
- addInitializer(changes, diag.file, propertyDeclaration, initializer);
- break;
- default:
- ts.Debug.fail(JSON.stringify(context.fixId));
- }
- });
- },
- });
- function getPropertyDeclaration(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- return ts.isIdentifier(token) ? ts.cast(token.parent, ts.isPropertyDeclaration) : undefined;
- }
- function getActionForAddMissingDefiniteAssignmentAssertion(context, propertyDeclaration) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addDefiniteAssignmentAssertion(t, context.sourceFile, propertyDeclaration); });
- return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_definite_assignment_assertion_to_property_0, propertyDeclaration.getText()], fixIdAddDefiniteAssignmentAssertions, ts.Diagnostics.Add_definite_assignment_assertions_to_all_uninitialized_properties);
- }
- function addDefiniteAssignmentAssertion(changeTracker, propertyDeclarationSourceFile, propertyDeclaration) {
- var property = ts.updateProperty(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, ts.createToken(53 /* ExclamationToken */), propertyDeclaration.type, propertyDeclaration.initializer);
- changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property);
- }
- function getActionForAddMissingUndefinedType(context, propertyDeclaration) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addUndefinedType(t, context.sourceFile, propertyDeclaration); });
- return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_undefined_type_to_property_0, propertyDeclaration.name.getText()], fixIdAddUndefinedType, ts.Diagnostics.Add_undefined_type_to_all_uninitialized_properties);
- }
- function addUndefinedType(changeTracker, propertyDeclarationSourceFile, propertyDeclaration) {
- var undefinedTypeNode = ts.createKeywordTypeNode(146 /* UndefinedKeyword */);
- var type = propertyDeclaration.type; // TODO: GH#18217
- var types = ts.isUnionTypeNode(type) ? type.types.concat(undefinedTypeNode) : [type, undefinedTypeNode];
- changeTracker.replaceNode(propertyDeclarationSourceFile, type, ts.createUnionTypeNode(types));
- }
- function getActionForAddMissingInitializer(context, propertyDeclaration) {
- var checker = context.program.getTypeChecker();
- var initializer = getInitializer(checker, propertyDeclaration);
- if (!initializer)
- return undefined;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addInitializer(t, context.sourceFile, propertyDeclaration, initializer); });
- return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_initializer_to_property_0, propertyDeclaration.name.getText()], fixIdAddInitializer, ts.Diagnostics.Add_initializers_to_all_uninitialized_properties);
- }
- function addInitializer(changeTracker, propertyDeclarationSourceFile, propertyDeclaration, initializer) {
- var property = ts.updateProperty(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, propertyDeclaration.questionToken, propertyDeclaration.type, initializer);
- changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property);
- }
- function getInitializer(checker, propertyDeclaration) {
- return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type)); // TODO: GH#18217
- }
- function getDefaultValueFromType(checker, type) {
- if (type.flags & 512 /* BooleanLiteral */) {
- return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? ts.createFalse() : ts.createTrue();
- }
- else if (type.isLiteral()) {
- return ts.createLiteral(type.value);
- }
- else if (type.isUnion()) {
- return ts.firstDefined(type.types, function (t) { return getDefaultValueFromType(checker, t); });
- }
- else if (type.isClass()) {
- var classDeclaration = ts.getClassLikeDeclarationOfSymbol(type.symbol);
- if (!classDeclaration || ts.hasModifier(classDeclaration, 128 /* Abstract */))
- return undefined;
- var constructorDeclaration = ts.getFirstConstructorWithBody(classDeclaration);
- if (constructorDeclaration && constructorDeclaration.parameters.length)
- return undefined;
- return ts.createNew(ts.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
- }
- else if (checker.isArrayLikeType(type)) {
- return ts.createArrayLiteral();
- }
- return undefined;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "requireInTs";
- var errorCodes = [ts.Diagnostics.require_call_may_be_converted_to_an_import.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, context.span.start, context.program); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_require_to_import, fixId, ts.Diagnostics.Convert_all_require_to_import)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, diag.start, context.program); }); },
- });
- function doChange(changes, sourceFile, pos, program) {
- var _a = getInfo(sourceFile, pos), statement = _a.statement, name = _a.name, required = _a.required;
- changes.replaceNode(sourceFile, statement, ts.getAllowSyntheticDefaultImports(program.getCompilerOptions())
- ? ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(name, /*namedBindings*/ undefined), required)
- : ts.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, name, ts.createExternalModuleReference(required)));
- }
- function getInfo(sourceFile, pos) {
- var parent = ts.getTokenAtPosition(sourceFile, pos).parent;
- if (!ts.isRequireCall(parent, /*checkArgumentIsStringLiteralLike*/ true))
- throw ts.Debug.failBadSyntaxKind(parent);
- var decl = ts.cast(parent.parent, ts.isVariableDeclaration);
- return { statement: ts.cast(decl.parent.parent, ts.isVariableStatement), name: ts.cast(decl.name, ts.isIdentifier), required: parent.arguments[0] };
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "useDefaultImport";
- var errorCodes = [ts.Diagnostics.Import_may_be_converted_to_a_default_import.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, start = context.span.start;
- var info = getInfo(sourceFile, start);
- if (!info)
- return undefined;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, info, context.preferences); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_to_default_import, fixId, ts.Diagnostics.Convert_all_to_default_imports)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var info = getInfo(diag.file, diag.start);
- if (info)
- doChange(changes, diag.file, info, context.preferences);
- }); },
- });
- function getInfo(sourceFile, pos) {
- var name = ts.getTokenAtPosition(sourceFile, pos);
- if (!ts.isIdentifier(name))
- return undefined; // bad input
- var parent = name.parent;
- if (ts.isImportEqualsDeclaration(parent) && ts.isExternalModuleReference(parent.moduleReference)) {
- return { importNode: parent, name: name, moduleSpecifier: parent.moduleReference.expression };
- }
- else if (ts.isNamespaceImport(parent)) {
- var importNode = parent.parent.parent;
- return { importNode: importNode, name: name, moduleSpecifier: importNode.moduleSpecifier };
- }
- }
- function doChange(changes, sourceFile, info, preferences) {
- changes.replaceNode(sourceFile, info.importNode, ts.makeImport(info.name, /*namedImports*/ undefined, info.moduleSpecifier, ts.getQuotePreference(sourceFile, preferences)));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "useBigintLiteral";
- var errorCodes = [
- ts.Diagnostics.Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span); });
- if (changes.length > 0) {
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_to_a_bigint_numeric_literal, fixId, ts.Diagnostics.Convert_all_to_bigint_numeric_literals)];
- }
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag); });
- },
- });
- function makeChange(changeTracker, sourceFile, span) {
- var numericLiteral = ts.tryCast(ts.getTokenAtPosition(sourceFile, span.start), ts.isNumericLiteral);
- if (!numericLiteral) {
- return;
- }
- // We use .getText to overcome parser inaccuracies: https://github.com/microsoft/TypeScript/issues/33298
- var newText = numericLiteral.getText(sourceFile) + "n";
- changeTracker.replaceNode(sourceFile, numericLiteral, ts.createBigIntLiteral(newText));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixIdAddMissingTypeof = "fixAddModuleReferTypeMissingTypeof";
- var fixId = fixIdAddMissingTypeof;
- var errorCodes = [ts.Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here_Did_you_mean_typeof_import_0.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var importType = getImportTypeNode(sourceFile, span.start);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, importType); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Add_missing_typeof, fixId, ts.Diagnostics.Add_missing_typeof)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- return doChange(changes, context.sourceFile, getImportTypeNode(diag.file, diag.start));
- }); },
- });
- function getImportTypeNode(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- ts.Debug.assert(token.kind === 96 /* ImportKeyword */, "This token should be an ImportKeyword");
- ts.Debug.assert(token.parent.kind === 188 /* ImportType */, "Token parent should be an ImportType");
- return token.parent;
- }
- function doChange(changes, sourceFile, importType) {
- var newTypeNode = ts.updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, /* isTypeOf */ true);
- changes.replaceNode(sourceFile, importType, newTypeNode);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixIdAddMissingTypeof = "fixConvertToMappedObjectType";
- var fixId = fixIdAddMissingTypeof;
- var errorCodes = [ts.Diagnostics.An_index_signature_parameter_type_cannot_be_a_union_type_Consider_using_a_mapped_object_type_instead.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var info = getInfo(sourceFile, span.start);
- if (!info)
- return undefined;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, info); });
- var name = ts.idText(info.container.name);
- return [codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Convert_0_to_mapped_object_type, name], fixId, [ts.Diagnostics.Convert_0_to_mapped_object_type, name])];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var info = getInfo(diag.file, diag.start);
- if (info)
- doChange(changes, diag.file, info);
- }); }
- });
- function getInfo(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- var indexSignature = ts.cast(token.parent.parent, ts.isIndexSignatureDeclaration);
- if (ts.isClassDeclaration(indexSignature.parent))
- return undefined;
- var container = ts.isInterfaceDeclaration(indexSignature.parent) ? indexSignature.parent : ts.cast(indexSignature.parent.parent, ts.isTypeAliasDeclaration);
- return { indexSignature: indexSignature, container: container };
- }
- function createTypeAliasFromInterface(declaration, type) {
- return ts.createTypeAliasDeclaration(declaration.decorators, declaration.modifiers, declaration.name, declaration.typeParameters, type);
- }
- function doChange(changes, sourceFile, _a) {
- var indexSignature = _a.indexSignature, container = _a.container;
- var members = ts.isInterfaceDeclaration(container) ? container.members : container.type.members;
- var otherMembers = members.filter(function (member) { return !ts.isIndexSignatureDeclaration(member); });
- var parameter = ts.first(indexSignature.parameters);
- var mappedTypeParameter = ts.createTypeParameterDeclaration(ts.cast(parameter.name, ts.isIdentifier), parameter.type);
- var mappedIntersectionType = ts.createMappedTypeNode(ts.hasReadonlyModifier(indexSignature) ? ts.createModifier(138 /* ReadonlyKeyword */) : undefined, mappedTypeParameter, indexSignature.questionToken, indexSignature.type);
- var intersectionType = ts.createIntersectionTypeNode(__spreadArrays(ts.getAllSuperTypeNodes(container), [
- mappedIntersectionType
- ], (otherMembers.length ? [ts.createTypeLiteralNode(otherMembers)] : ts.emptyArray)));
- changes.replaceNode(sourceFile, container, createTypeAliasFromInterface(container, intersectionType));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "removeUnnecessaryAwait";
- var errorCodes = [
- ts.Diagnostics.await_has_no_effect_on_the_type_of_this_expression.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span); });
- if (changes.length > 0) {
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Remove_unnecessary_await, fixId, ts.Diagnostics.Remove_all_unnecessary_uses_of_await)];
- }
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag); });
- },
- });
- function makeChange(changeTracker, sourceFile, span) {
- var awaitKeyword = ts.tryCast(ts.getTokenAtPosition(sourceFile, span.start), function (node) { return node.kind === 127 /* AwaitKeyword */; });
- var awaitExpression = awaitKeyword && ts.tryCast(awaitKeyword.parent, ts.isAwaitExpression);
- if (!awaitExpression) {
- return;
- }
- var expressionToReplace = awaitExpression;
- var hasSurroundingParens = ts.isParenthesizedExpression(awaitExpression.parent);
- if (hasSurroundingParens) {
- var leftMostExpression = ts.getLeftmostExpression(awaitExpression.expression, /*stopAtCallExpressions*/ false);
- if (ts.isIdentifier(leftMostExpression)) {
- var precedingToken = ts.findPrecedingToken(awaitExpression.parent.pos, sourceFile);
- if (precedingToken && precedingToken.kind !== 99 /* NewKeyword */) {
- expressionToReplace = awaitExpression.parent;
- }
- }
- }
- changeTracker.replaceNode(sourceFile, expressionToReplace, awaitExpression.expression);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodes = [ts.Diagnostics.A_type_only_import_can_specify_a_default_import_or_named_bindings_but_not_both.code];
- var fixId = "splitTypeOnlyImport";
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- fixIds: [fixId],
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) {
- return splitTypeOnlyImport(t, getImportDeclaration(context.sourceFile, context.span), context);
- });
- if (changes.length) {
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Split_into_two_separate_import_declarations, fixId, ts.Diagnostics.Split_all_invalid_type_only_imports)];
- }
- },
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, error) {
- splitTypeOnlyImport(changes, getImportDeclaration(context.sourceFile, error), context);
- }); },
- });
- function getImportDeclaration(sourceFile, span) {
- return ts.findAncestor(ts.getTokenAtPosition(sourceFile, span.start), ts.isImportDeclaration);
- }
- function splitTypeOnlyImport(changes, importDeclaration, context) {
- if (!importDeclaration) {
- return;
- }
- var importClause = ts.Debug.checkDefined(importDeclaration.importClause);
- changes.replaceNode(context.sourceFile, importDeclaration, ts.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.updateImportClause(importClause, importClause.name, /*namedBindings*/ undefined, importClause.isTypeOnly), importDeclaration.moduleSpecifier));
- changes.insertNodeAfter(context.sourceFile, importDeclaration, ts.createImportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.updateImportClause(importClause, /*name*/ undefined, importClause.namedBindings, importClause.isTypeOnly), importDeclaration.moduleSpecifier));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixConvertConstToLet";
- var errorCodes = [ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_constant.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span, program = context.program;
- var variableStatement = getVariableStatement(sourceFile, span.start, program);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, variableStatement); });
- return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_const_to_let, fixId, ts.Diagnostics.Convert_const_to_let)];
- },
- fixIds: [fixId]
- });
- function getVariableStatement(sourceFile, pos, program) {
- var token = ts.getTokenAtPosition(sourceFile, pos);
- var checker = program.getTypeChecker();
- var symbol = checker.getSymbolAtLocation(token);
- if (symbol) {
- return symbol.valueDeclaration.parent.parent;
- }
- }
- function doChange(changes, sourceFile, variableStatement) {
- if (!variableStatement) {
- return;
- }
- var start = variableStatement.getStart();
- changes.replaceRangeWithText(sourceFile, { pos: start, end: start + 5 }, "let");
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixExpectedComma";
- var expectedErrorCode = ts.Diagnostics._0_expected.code;
- var errorCodes = [expectedErrorCode];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var info = getInfo(sourceFile, context.span.start, context.errorCode);
- if (!info) {
- return undefined;
- }
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, info); });
- return [codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Change_0_to_1, ";", ","], fixId, [ts.Diagnostics.Change_0_to_1, ";", ","])];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var info = getInfo(diag.file, diag.start, diag.code);
- if (info)
- doChange(changes, context.sourceFile, info);
- }); },
- });
- function getInfo(sourceFile, pos, _) {
- var node = ts.getTokenAtPosition(sourceFile, pos);
- return (node.kind === 26 /* SemicolonToken */ &&
- node.parent &&
- (ts.isObjectLiteralExpression(node.parent) ||
- ts.isArrayLiteralExpression(node.parent))) ? { node: node } : undefined;
- }
- function doChange(changes, sourceFile, _a) {
- var node = _a.node;
- var newNode = ts.createNode(27 /* CommaToken */);
- changes.replaceNode(sourceFile, node, newNode);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var refactor;
- (function (refactor) {
- var refactorName = "Convert export";
- var actionNameDefaultToNamed = "Convert default export to named export";
- var actionNameNamedToDefault = "Convert named export to default export";
- refactor.registerRefactor(refactorName, {
- getAvailableActions: function (context) {
- var info = getInfo(context);
- if (!info)
- return ts.emptyArray;
- var description = info.wasDefault ? ts.Diagnostics.Convert_default_export_to_named_export.message : ts.Diagnostics.Convert_named_export_to_default_export.message;
- var actionName = info.wasDefault ? actionNameDefaultToNamed : actionNameNamedToDefault;
- return [{ name: refactorName, description: description, actions: [{ name: actionName, description: description }] }];
- },
- getEditsForAction: function (context, actionName) {
- ts.Debug.assert(actionName === actionNameDefaultToNamed || actionName === actionNameNamedToDefault, "Unexpected action name");
- var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(context.file, context.program, ts.Debug.checkDefined(getInfo(context), "context must have info"), t, context.cancellationToken); });
- return { edits: edits, renameFilename: undefined, renameLocation: undefined };
- },
- });
- function getInfo(context) {
- var file = context.file;
- var span = ts.getRefactorContextSpan(context);
- var token = ts.getTokenAtPosition(file, span.start);
- var exportNode = ts.getParentNodeInSpan(token, file, span);
- if (!exportNode || (!ts.isSourceFile(exportNode.parent) && !(ts.isModuleBlock(exportNode.parent) && ts.isAmbientModule(exportNode.parent.parent)))) {
- return undefined;
- }
- var exportingModuleSymbol = ts.isSourceFile(exportNode.parent) ? exportNode.parent.symbol : exportNode.parent.parent.symbol;
- var flags = ts.getModifierFlags(exportNode);
- var wasDefault = !!(flags & 512 /* Default */);
- // If source file already has a default export, don't offer refactor.
- if (!(flags & 1 /* Export */) || !wasDefault && exportingModuleSymbol.exports.has("default" /* Default */)) {
- return undefined;
- }
- switch (exportNode.kind) {
- case 244 /* FunctionDeclaration */:
- case 245 /* ClassDeclaration */:
- case 246 /* InterfaceDeclaration */:
- case 248 /* EnumDeclaration */:
- case 247 /* TypeAliasDeclaration */:
- case 249 /* ModuleDeclaration */: {
- var node = exportNode;
- return node.name && ts.isIdentifier(node.name) ? { exportNode: node, exportName: node.name, wasDefault: wasDefault, exportingModuleSymbol: exportingModuleSymbol } : undefined;
- }
- case 225 /* VariableStatement */: {
- var vs = exportNode;
- // Must be `export const x = something;`.
- if (!(vs.declarationList.flags & 2 /* Const */) || vs.declarationList.declarations.length !== 1) {
- return undefined;
- }
- var decl = ts.first(vs.declarationList.declarations);
- if (!decl.initializer)
- return undefined;
- ts.Debug.assert(!wasDefault, "Can't have a default flag here");
- return ts.isIdentifier(decl.name) ? { exportNode: vs, exportName: decl.name, wasDefault: wasDefault, exportingModuleSymbol: exportingModuleSymbol } : undefined;
- }
- default:
- return undefined;
- }
- }
- function doChange(exportingSourceFile, program, info, changes, cancellationToken) {
- changeExport(exportingSourceFile, info, changes, program.getTypeChecker());
- changeImports(program, info, changes, cancellationToken);
- }
- function changeExport(exportingSourceFile, _a, changes, checker) {
- var wasDefault = _a.wasDefault, exportNode = _a.exportNode, exportName = _a.exportName;
- if (wasDefault) {
- changes.delete(exportingSourceFile, ts.Debug.checkDefined(ts.findModifier(exportNode, 84 /* DefaultKeyword */), "Should find a default keyword in modifier list"));
- }
- else {
- var exportKeyword = ts.Debug.checkDefined(ts.findModifier(exportNode, 89 /* ExportKeyword */), "Should find an export keyword in modifier list");
- switch (exportNode.kind) {
- case 244 /* FunctionDeclaration */:
- case 245 /* ClassDeclaration */:
- case 246 /* InterfaceDeclaration */:
- changes.insertNodeAfter(exportingSourceFile, exportKeyword, ts.createToken(84 /* DefaultKeyword */));
- break;
- case 225 /* VariableStatement */:
- // If 'x' isn't used in this file, `export const x = 0;` --> `export default 0;`
- if (!ts.FindAllReferences.Core.isSymbolReferencedInFile(exportName, checker, exportingSourceFile)) {
- // We checked in `getInfo` that an initializer exists.
- changes.replaceNode(exportingSourceFile, exportNode, ts.createExportDefault(ts.Debug.checkDefined(ts.first(exportNode.declarationList.declarations).initializer, "Initializer was previously known to be present")));
- break;
- }
- // falls through
- case 248 /* EnumDeclaration */:
- case 247 /* TypeAliasDeclaration */:
- case 249 /* ModuleDeclaration */:
- // `export type T = number;` -> `type T = number; export default T;`
- changes.deleteModifier(exportingSourceFile, exportKeyword);
- changes.insertNodeAfter(exportingSourceFile, exportNode, ts.createExportDefault(ts.createIdentifier(exportName.text)));
- break;
- default:
- ts.Debug.assertNever(exportNode, "Unexpected exportNode kind " + exportNode.kind);
- }
- }
- }
- function changeImports(program, _a, changes, cancellationToken) {
- var wasDefault = _a.wasDefault, exportName = _a.exportName, exportingModuleSymbol = _a.exportingModuleSymbol;
- var checker = program.getTypeChecker();
- var exportSymbol = ts.Debug.checkDefined(checker.getSymbolAtLocation(exportName), "Export name should resolve to a symbol");
- ts.FindAllReferences.Core.eachExportReference(program.getSourceFiles(), checker, cancellationToken, exportSymbol, exportingModuleSymbol, exportName.text, wasDefault, function (ref) {
- var importingSourceFile = ref.getSourceFile();
- if (wasDefault) {
- changeDefaultToNamedImport(importingSourceFile, ref, changes, exportName.text);
- }
- else {
- changeNamedToDefaultImport(importingSourceFile, ref, changes);
- }
- });
- }
- function changeDefaultToNamedImport(importingSourceFile, ref, changes, exportName) {
- var parent = ref.parent;
- switch (parent.kind) {
- case 194 /* PropertyAccessExpression */:
- // `a.default` --> `a.foo`
- changes.replaceNode(importingSourceFile, ref, ts.createIdentifier(exportName));
- break;
- case 258 /* ImportSpecifier */:
- case 263 /* ExportSpecifier */: {
- var spec = parent;
- // `default as foo` --> `foo`, `default as bar` --> `foo as bar`
- changes.replaceNode(importingSourceFile, spec, makeImportSpecifier(exportName, spec.name.text));
- break;
- }
- case 255 /* ImportClause */: {
- var clause = parent;
- ts.Debug.assert(clause.name === ref, "Import clause name should match provided ref");
- var spec = makeImportSpecifier(exportName, ref.text);
- var namedBindings = clause.namedBindings;
- if (!namedBindings) {
- // `import foo from "./a";` --> `import { foo } from "./a";`
- changes.replaceNode(importingSourceFile, ref, ts.createNamedImports([spec]));
- }
- else if (namedBindings.kind === 256 /* NamespaceImport */) {
- // `import foo, * as a from "./a";` --> `import * as a from ".a/"; import { foo } from "./a";`
- changes.deleteRange(importingSourceFile, { pos: ref.getStart(importingSourceFile), end: namedBindings.getStart(importingSourceFile) });
- var quotePreference = ts.isStringLiteral(clause.parent.moduleSpecifier) ? ts.quotePreferenceFromString(clause.parent.moduleSpecifier, importingSourceFile) : 1 /* Double */;
- var newImport = ts.makeImport(/*default*/ undefined, [makeImportSpecifier(exportName, ref.text)], clause.parent.moduleSpecifier, quotePreference);
- changes.insertNodeAfter(importingSourceFile, clause.parent, newImport);
- }
- else {
- // `import foo, { bar } from "./a"` --> `import { bar, foo } from "./a";`
- changes.delete(importingSourceFile, ref);
- changes.insertNodeAtEndOfList(importingSourceFile, namedBindings.elements, spec);
- }
- break;
- }
- default:
- ts.Debug.failBadSyntaxKind(parent);
- }
- }
- function changeNamedToDefaultImport(importingSourceFile, ref, changes) {
- var parent = ref.parent;
- switch (parent.kind) {
- case 194 /* PropertyAccessExpression */:
- // `a.foo` --> `a.default`
- changes.replaceNode(importingSourceFile, ref, ts.createIdentifier("default"));
- break;
- case 258 /* ImportSpecifier */: {
- // `import { foo } from "./a";` --> `import foo from "./a";`
- // `import { foo as bar } from "./a";` --> `import bar from "./a";`
- var defaultImport = ts.createIdentifier(parent.name.text);
- if (parent.parent.elements.length === 1) {
- changes.replaceNode(importingSourceFile, parent.parent, defaultImport);
- }
- else {
- changes.delete(importingSourceFile, parent);
- changes.insertNodeBefore(importingSourceFile, parent.parent, defaultImport);
- }
- break;
- }
- case 263 /* ExportSpecifier */: {
- // `export { foo } from "./a";` --> `export { default as foo } from "./a";`
- // `export { foo as bar } from "./a";` --> `export { default as bar } from "./a";`
- // `export { foo as default } from "./a";` --> `export { default } from "./a";`
- // (Because `export foo from "./a";` isn't valid syntax.)
- changes.replaceNode(importingSourceFile, parent, makeExportSpecifier("default", parent.name.text));
- break;
- }
- default:
- ts.Debug.assertNever(parent, "Unexpected parent kind " + parent.kind);
- }
- }
- function makeImportSpecifier(propertyName, name) {
- return ts.createImportSpecifier(propertyName === name ? undefined : ts.createIdentifier(propertyName), ts.createIdentifier(name));
- }
- function makeExportSpecifier(propertyName, name) {
- return ts.createExportSpecifier(propertyName === name ? undefined : ts.createIdentifier(propertyName), ts.createIdentifier(name));
- }
- })(refactor = ts.refactor || (ts.refactor = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var refactor;
- (function (refactor) {
- var refactorName = "Convert import";
- var actionNameNamespaceToNamed = "Convert namespace import to named imports";
- var actionNameNamedToNamespace = "Convert named imports to namespace import";
- refactor.registerRefactor(refactorName, {
- getAvailableActions: function (context) {
- var i = getImportToConvert(context);
- if (!i)
- return ts.emptyArray;
- var description = i.kind === 256 /* NamespaceImport */ ? ts.Diagnostics.Convert_namespace_import_to_named_imports.message : ts.Diagnostics.Convert_named_imports_to_namespace_import.message;
- var actionName = i.kind === 256 /* NamespaceImport */ ? actionNameNamespaceToNamed : actionNameNamedToNamespace;
- return [{ name: refactorName, description: description, actions: [{ name: actionName, description: description }] }];
- },
- getEditsForAction: function (context, actionName) {
- ts.Debug.assert(actionName === actionNameNamespaceToNamed || actionName === actionNameNamedToNamespace, "Unexpected action name");
- var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(context.file, context.program, t, ts.Debug.checkDefined(getImportToConvert(context), "Context must provide an import to convert")); });
- return { edits: edits, renameFilename: undefined, renameLocation: undefined };
- }
- });
- // Can convert imports of the form `import * as m from "m";` or `import d, { x, y } from "m";`.
- function getImportToConvert(context) {
- var file = context.file;
- var span = ts.getRefactorContextSpan(context);
- var token = ts.getTokenAtPosition(file, span.start);
- var importDecl = ts.getParentNodeInSpan(token, file, span);
- if (!importDecl || !ts.isImportDeclaration(importDecl))
- return undefined;
- var importClause = importDecl.importClause;
- return importClause && importClause.namedBindings;
- }
- function doChange(sourceFile, program, changes, toConvert) {
- var checker = program.getTypeChecker();
- if (toConvert.kind === 256 /* NamespaceImport */) {
- doChangeNamespaceToNamed(sourceFile, checker, changes, toConvert, ts.getAllowSyntheticDefaultImports(program.getCompilerOptions()));
- }
- else {
- doChangeNamedToNamespace(sourceFile, checker, changes, toConvert);
- }
- }
- function doChangeNamespaceToNamed(sourceFile, checker, changes, toConvert, allowSyntheticDefaultImports) {
- var usedAsNamespaceOrDefault = false;
- var nodesToReplace = [];
- var conflictingNames = ts.createMap();
- ts.FindAllReferences.Core.eachSymbolReferenceInFile(toConvert.name, checker, sourceFile, function (id) {
- if (!ts.isPropertyAccessExpression(id.parent)) {
- usedAsNamespaceOrDefault = true;
- }
- else {
- var parent = ts.cast(id.parent, ts.isPropertyAccessExpression);
- var exportName = parent.name.text;
- if (checker.resolveName(exportName, id, 67108863 /* All */, /*excludeGlobals*/ true)) {
- conflictingNames.set(exportName, true);
- }
- ts.Debug.assert(parent.expression === id, "Parent expression should match id");
- nodesToReplace.push(parent);
- }
- });
- // We may need to change `mod.x` to `_x` to avoid a name conflict.
- var exportNameToImportName = ts.createMap();
- for (var _i = 0, nodesToReplace_1 = nodesToReplace; _i < nodesToReplace_1.length; _i++) {
- var propertyAccess = nodesToReplace_1[_i];
- var exportName = propertyAccess.name.text;
- var importName = exportNameToImportName.get(exportName);
- if (importName === undefined) {
- exportNameToImportName.set(exportName, importName = conflictingNames.has(exportName) ? ts.getUniqueName(exportName, sourceFile) : exportName);
- }
- changes.replaceNode(sourceFile, propertyAccess, ts.createIdentifier(importName));
- }
- var importSpecifiers = [];
- exportNameToImportName.forEach(function (name, propertyName) {
- importSpecifiers.push(ts.createImportSpecifier(name === propertyName ? undefined : ts.createIdentifier(propertyName), ts.createIdentifier(name)));
- });
- var importDecl = toConvert.parent.parent;
- if (usedAsNamespaceOrDefault && !allowSyntheticDefaultImports) {
- // Need to leave the namespace import alone
- changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers));
- }
- else {
- changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? ts.createIdentifier(toConvert.name.text) : undefined, importSpecifiers));
- }
- }
- function doChangeNamedToNamespace(sourceFile, checker, changes, toConvert) {
- var importDecl = toConvert.parent.parent;
- var moduleSpecifier = importDecl.moduleSpecifier;
- var preferredName = moduleSpecifier && ts.isStringLiteral(moduleSpecifier) ? ts.codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, 99 /* ESNext */) : "module";
- var namespaceNameConflicts = toConvert.elements.some(function (element) {
- return ts.FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, function (id) {
- return !!checker.resolveName(preferredName, id, 67108863 /* All */, /*excludeGlobals*/ true);
- }) || false;
- });
- var namespaceImportName = namespaceNameConflicts ? ts.getUniqueName(preferredName, sourceFile) : preferredName;
- var neededNamedImports = [];
- var _loop_15 = function (element) {
- var propertyName = (element.propertyName || element.name).text;
- ts.FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, function (id) {
- var access = ts.createPropertyAccess(ts.createIdentifier(namespaceImportName), propertyName);
- if (ts.isShorthandPropertyAssignment(id.parent)) {
- changes.replaceNode(sourceFile, id.parent, ts.createPropertyAssignment(id.text, access));
- }
- else if (ts.isExportSpecifier(id.parent) && !id.parent.propertyName) {
- if (!neededNamedImports.some(function (n) { return n.name === element.name; })) {
- neededNamedImports.push(ts.createImportSpecifier(element.propertyName && ts.createIdentifier(element.propertyName.text), ts.createIdentifier(element.name.text)));
- }
- }
- else {
- changes.replaceNode(sourceFile, id, access);
- }
- });
- };
- for (var _i = 0, _a = toConvert.elements; _i < _a.length; _i++) {
- var element = _a[_i];
- _loop_15(element);
- }
- changes.replaceNode(sourceFile, toConvert, ts.createNamespaceImport(ts.createIdentifier(namespaceImportName)));
- if (neededNamedImports.length) {
- changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, neededNamedImports));
- }
- }
- function updateImport(old, defaultImportName, elements) {
- return ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.createImportClause(defaultImportName, elements && elements.length ? ts.createNamedImports(elements) : undefined), old.moduleSpecifier);
- }
- })(refactor = ts.refactor || (ts.refactor = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var refactor;
- (function (refactor) {
- var extractSymbol;
- (function (extractSymbol) {
- var refactorName = "Extract Symbol";
- refactor.registerRefactor(refactorName, { getAvailableActions: getAvailableActions, getEditsForAction: getEditsForAction });
- /**
- * Compute the associated code actions
- * Exported for tests.
- */
- function getAvailableActions(context) {
- var rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context));
- var targetRange = rangeToExtract.targetRange;
- if (targetRange === undefined) {
- return ts.emptyArray;
- }
- var extractions = getPossibleExtractions(targetRange, context);
- if (extractions === undefined) {
- // No extractions possible
- return ts.emptyArray;
- }
- var functionActions = [];
- var usedFunctionNames = ts.createMap();
- var constantActions = [];
- var usedConstantNames = ts.createMap();
- var i = 0;
- for (var _i = 0, extractions_1 = extractions; _i < extractions_1.length; _i++) {
- var _a = extractions_1[_i], functionExtraction = _a.functionExtraction, constantExtraction = _a.constantExtraction;
- // Skip these since we don't have a way to report errors yet
- if (functionExtraction.errors.length === 0) {
- // Don't issue refactorings with duplicated names.
- // Scopes come back in "innermost first" order, so extractions will
- // preferentially go into nearer scopes
- var description = functionExtraction.description;
- if (!usedFunctionNames.has(description)) {
- usedFunctionNames.set(description, true);
- functionActions.push({
- description: description,
- name: "function_scope_" + i
- });
- }
- }
- // Skip these since we don't have a way to report errors yet
- if (constantExtraction.errors.length === 0) {
- // Don't issue refactorings with duplicated names.
- // Scopes come back in "innermost first" order, so extractions will
- // preferentially go into nearer scopes
- var description = constantExtraction.description;
- if (!usedConstantNames.has(description)) {
- usedConstantNames.set(description, true);
- constantActions.push({
- description: description,
- name: "constant_scope_" + i
- });
- }
- }
- // *do* increment i anyway because we'll look for the i-th scope
- // later when actually doing the refactoring if the user requests it
- i++;
- }
- var infos = [];
- if (constantActions.length) {
- infos.push({
- name: refactorName,
- description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_constant),
- actions: constantActions
- });
- }
- if (functionActions.length) {
- infos.push({
- name: refactorName,
- description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_function),
- actions: functionActions
- });
- }
- return infos.length ? infos : ts.emptyArray;
- }
- extractSymbol.getAvailableActions = getAvailableActions;
- /* Exported for tests */
- function getEditsForAction(context, actionName) {
- var rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context));
- var targetRange = rangeToExtract.targetRange; // TODO:GH#18217
- var parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName);
- if (parsedFunctionIndexMatch) {
- var index = +parsedFunctionIndexMatch[1];
- ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the function scope index");
- return getFunctionExtractionAtIndex(targetRange, context, index);
- }
- var parsedConstantIndexMatch = /^constant_scope_(\d+)$/.exec(actionName);
- if (parsedConstantIndexMatch) {
- var index = +parsedConstantIndexMatch[1];
- ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the constant scope index");
- return getConstantExtractionAtIndex(targetRange, context, index);
- }
- ts.Debug.fail("Unrecognized action name");
- }
- extractSymbol.getEditsForAction = getEditsForAction;
- // Move these into diagnostic messages if they become user-facing
- var Messages;
- (function (Messages) {
- function createMessage(message) {
- return { message: message, code: 0, category: ts.DiagnosticCategory.Message, key: message };
- }
- Messages.cannotExtractRange = createMessage("Cannot extract range.");
- Messages.cannotExtractImport = createMessage("Cannot extract import statement.");
- Messages.cannotExtractSuper = createMessage("Cannot extract super call.");
- Messages.cannotExtractJSDoc = createMessage("Cannot extract JSDoc.");
- Messages.cannotExtractEmpty = createMessage("Cannot extract empty range.");
- Messages.expressionExpected = createMessage("expression expected.");
- Messages.uselessConstantType = createMessage("No reason to extract constant of type.");
- Messages.statementOrExpressionExpected = createMessage("Statement or expression expected.");
- Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements = createMessage("Cannot extract range containing conditional break or continue statements.");
- Messages.cannotExtractRangeContainingConditionalReturnStatement = createMessage("Cannot extract range containing conditional return statement.");
- Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange = createMessage("Cannot extract range containing labeled break or continue with target outside of the range.");
- Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators = createMessage("Cannot extract range containing writes to references located outside of the target range in generators.");
- Messages.typeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope.");
- Messages.functionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope.");
- Messages.cannotExtractIdentifier = createMessage("Select more than a single identifier.");
- Messages.cannotExtractExportedEntity = createMessage("Cannot extract exported declaration");
- Messages.cannotWriteInExpression = createMessage("Cannot write back side-effects when extracting an expression");
- Messages.cannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor");
- Messages.cannotExtractAmbientBlock = createMessage("Cannot extract code from ambient contexts");
- Messages.cannotAccessVariablesFromNestedScopes = createMessage("Cannot access variables from nested scopes");
- Messages.cannotExtractToOtherFunctionLike = createMessage("Cannot extract method to a function-like scope that is not a function");
- Messages.cannotExtractToJSClass = createMessage("Cannot extract constant to a class scope in JS");
- Messages.cannotExtractToExpressionArrowFunction = createMessage("Cannot extract constant to an arrow function without a block");
- })(Messages = extractSymbol.Messages || (extractSymbol.Messages = {}));
- var RangeFacts;
- (function (RangeFacts) {
- RangeFacts[RangeFacts["None"] = 0] = "None";
- RangeFacts[RangeFacts["HasReturn"] = 1] = "HasReturn";
- RangeFacts[RangeFacts["IsGenerator"] = 2] = "IsGenerator";
- RangeFacts[RangeFacts["IsAsyncFunction"] = 4] = "IsAsyncFunction";
- RangeFacts[RangeFacts["UsesThis"] = 8] = "UsesThis";
- /**
- * The range is in a function which needs the 'static' modifier in a class
- */
- RangeFacts[RangeFacts["InStaticRegion"] = 16] = "InStaticRegion";
- })(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;
- if (length === 0) {
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractEmpty)] };
- }
- // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span.
- // This may fail (e.g. you select two statements in the root of a source file)
- var start = ts.getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start), sourceFile, span);
- // Do the same for the ending position
- var end = ts.getParentNodeInSpan(ts.findTokenOnLeftOfPosition(sourceFile, ts.textSpanEnd(span)), sourceFile, span);
- var declarations = [];
- // We'll modify these flags as we walk the tree to collect data
- // about what things need to be done as part of the extraction.
- var rangeFacts = RangeFacts.None;
- if (!start || !end) {
- // cannot find either start or end node
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- if (start.parent !== end.parent) {
- // start and end nodes belong to different subtrees
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- if (start !== end) {
- // start and end should be statements and parent should be either block or a source file
- if (!isBlockLike(start.parent)) {
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- var statements = [];
- var start2 = start; // TODO: GH#18217 Need to alias `start` to get this to compile. See https://github.com/Microsoft/TypeScript/issues/19955#issuecomment-344118248
- for (var _i = 0, _a = start2.parent.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- if (statement === start || statements.length) {
- var errors_1 = checkNode(statement);
- if (errors_1) {
- return { errors: errors_1 };
- }
- statements.push(statement);
- }
- if (statement === end) {
- break;
- }
- }
- if (!statements.length) {
- // https://github.com/Microsoft/TypeScript/issues/20559
- // Ranges like [|case 1: break;|] will fail to populate `statements` because
- // they will never find `start` in `start.parent.statements`.
- // Consider: We could support ranges like [|case 1:|] by refining them to just
- // the expression.
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- return { targetRange: { range: statements, facts: rangeFacts, declarations: declarations } };
- }
- if (ts.isJSDoc(start)) {
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractJSDoc)] };
- }
- if (ts.isReturnStatement(start) && !start.expression) {
- // Makes no sense to extract an expression-less return statement.
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- // We have a single node (start)
- var node = refineNode(start);
- var errors = checkRootNode(node) || checkNode(node);
- if (errors) {
- return { errors: errors };
- }
- return { targetRange: { range: getStatementOrExpressionRange(node), facts: rangeFacts, declarations: declarations } }; // TODO: GH#18217
- /**
- * Attempt to refine the extraction node (generally, by shrinking it) to produce better results.
- * @param node The unrefined extraction node.
- */
- function refineNode(node) {
- if (ts.isReturnStatement(node)) {
- if (node.expression) {
- return node.expression;
- }
- }
- else if (ts.isVariableStatement(node)) {
- var numInitializers = 0;
- var lastInitializer = void 0;
- for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (declaration.initializer) {
- numInitializers++;
- lastInitializer = declaration.initializer;
- }
- }
- if (numInitializers === 1) {
- return lastInitializer;
- }
- // No special handling if there are multiple initializers.
- }
- else if (ts.isVariableDeclaration(node)) {
- if (node.initializer) {
- return node.initializer;
- }
- }
- return node;
- }
- function checkRootNode(node) {
- if (ts.isIdentifier(ts.isExpressionStatement(node) ? node.expression : node)) {
- return [ts.createDiagnosticForNode(node, Messages.cannotExtractIdentifier)];
- }
- return undefined;
- }
- function checkForStaticContext(nodeToCheck, containingClass) {
- var current = nodeToCheck;
- while (current !== containingClass) {
- if (current.kind === 159 /* PropertyDeclaration */) {
- if (ts.hasModifier(current, 32 /* Static */)) {
- rangeFacts |= RangeFacts.InStaticRegion;
- }
- break;
- }
- else if (current.kind === 156 /* Parameter */) {
- var ctorOrMethod = ts.getContainingFunction(current);
- if (ctorOrMethod.kind === 162 /* Constructor */) {
- rangeFacts |= RangeFacts.InStaticRegion;
- }
- break;
- }
- else if (current.kind === 161 /* MethodDeclaration */) {
- if (ts.hasModifier(current, 32 /* Static */)) {
- rangeFacts |= RangeFacts.InStaticRegion;
- }
- }
- current = current.parent;
- }
- }
- // Verifies whether we can actually extract this node or not.
- function checkNode(nodeToCheck) {
- var PermittedJumps;
- (function (PermittedJumps) {
- PermittedJumps[PermittedJumps["None"] = 0] = "None";
- PermittedJumps[PermittedJumps["Break"] = 1] = "Break";
- PermittedJumps[PermittedJumps["Continue"] = 2] = "Continue";
- PermittedJumps[PermittedJumps["Return"] = 4] = "Return";
- })(PermittedJumps || (PermittedJumps = {}));
- // We believe it's true because the node is from the (unmodified) tree.
- ts.Debug.assert(nodeToCheck.pos <= nodeToCheck.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (1)");
- // For understanding how skipTrivia functioned:
- ts.Debug.assert(!ts.positionIsSynthesized(nodeToCheck.pos), "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (2)");
- if (!ts.isStatement(nodeToCheck) && !(ts.isExpressionNode(nodeToCheck) && isExtractableExpression(nodeToCheck))) {
- return [ts.createDiagnosticForNode(nodeToCheck, Messages.statementOrExpressionExpected)];
- }
- if (nodeToCheck.flags & 8388608 /* Ambient */) {
- return [ts.createDiagnosticForNode(nodeToCheck, Messages.cannotExtractAmbientBlock)];
- }
- // If we're in a class, see whether we're in a static region (static property initializer, static method, class constructor parameter default)
- var containingClass = ts.getContainingClass(nodeToCheck);
- if (containingClass) {
- checkForStaticContext(nodeToCheck, containingClass);
- }
- var errors;
- var permittedJumps = 4 /* Return */;
- var seenLabels;
- visit(nodeToCheck);
- return errors;
- function visit(node) {
- if (errors) {
- // already found an error - can stop now
- return true;
- }
- if (ts.isDeclaration(node)) {
- var declaringNode = (node.kind === 242 /* VariableDeclaration */) ? node.parent.parent : node;
- if (ts.hasModifier(declaringNode, 1 /* Export */)) {
- // TODO: GH#18217 Silly to use `errors ||` since it's definitely not defined (see top of `visit`)
- // Also, if we're only pushing one error, just use `let error: Diagnostic | undefined`!
- // Also TODO: GH#19956
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractExportedEntity));
- return true;
- }
- declarations.push(node.symbol);
- }
- // Some things can't be extracted in certain situations
- switch (node.kind) {
- case 254 /* ImportDeclaration */:
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractImport));
- return true;
- case 102 /* SuperKeyword */:
- // For a super *constructor call*, we have to be extracting the entire class,
- // but a super *method call* simply implies a 'this' reference
- if (node.parent.kind === 196 /* CallExpression */) {
- // Super constructor call
- var containingClass_1 = ts.getContainingClass(node); // TODO:GH#18217
- if (containingClass_1.pos < span.start || containingClass_1.end >= (span.start + span.length)) {
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractSuper));
- return true;
- }
- }
- else {
- rangeFacts |= RangeFacts.UsesThis;
- }
- break;
- }
- if (ts.isFunctionLikeDeclaration(node) || ts.isClassLike(node)) {
- switch (node.kind) {
- case 244 /* FunctionDeclaration */:
- case 245 /* ClassDeclaration */:
- if (ts.isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) {
- // You cannot extract global declarations
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope));
- }
- break;
- }
- // do not dive into functions or classes
- return false;
- }
- var savedPermittedJumps = permittedJumps;
- switch (node.kind) {
- case 227 /* IfStatement */:
- permittedJumps = 0 /* None */;
- break;
- case 240 /* TryStatement */:
- // forbid all jumps inside try blocks
- permittedJumps = 0 /* None */;
- break;
- case 223 /* Block */:
- if (node.parent && node.parent.kind === 240 /* TryStatement */ && node.parent.finallyBlock === node) {
- // allow unconditional returns from finally blocks
- permittedJumps = 4 /* Return */;
- }
- break;
- case 278 /* DefaultClause */:
- case 277 /* CaseClause */:
- // allow unlabeled break inside case clauses
- permittedJumps |= 1 /* Break */;
- break;
- default:
- if (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false)) {
- // allow unlabeled break/continue inside loops
- permittedJumps |= 1 /* Break */ | 2 /* Continue */;
- }
- break;
- }
- switch (node.kind) {
- case 183 /* ThisType */:
- case 104 /* ThisKeyword */:
- rangeFacts |= RangeFacts.UsesThis;
- break;
- case 238 /* LabeledStatement */: {
- var label = node.label;
- (seenLabels || (seenLabels = [])).push(label.escapedText);
- ts.forEachChild(node, visit);
- seenLabels.pop();
- break;
- }
- case 234 /* BreakStatement */:
- case 233 /* ContinueStatement */: {
- var label = node.label;
- if (label) {
- if (!ts.contains(seenLabels, label.escapedText)) {
- // attempts to jump to label that is not in range to be extracted
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange));
- }
- }
- else {
- if (!(permittedJumps & (node.kind === 234 /* BreakStatement */ ? 1 /* Break */ : 2 /* Continue */))) {
- // attempt to break or continue in a forbidden context
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements));
- }
- }
- break;
- }
- case 206 /* AwaitExpression */:
- rangeFacts |= RangeFacts.IsAsyncFunction;
- break;
- case 212 /* YieldExpression */:
- rangeFacts |= RangeFacts.IsGenerator;
- break;
- case 235 /* ReturnStatement */:
- if (permittedJumps & 4 /* Return */) {
- rangeFacts |= RangeFacts.HasReturn;
- }
- else {
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement));
- }
- break;
- default:
- ts.forEachChild(node, visit);
- break;
- }
- permittedJumps = savedPermittedJumps;
- }
- }
- }
- extractSymbol.getRangeToExtract = getRangeToExtract;
- function getStatementOrExpressionRange(node) {
- if (ts.isStatement(node)) {
- return [node];
- }
- else if (ts.isExpressionNode(node)) {
- // If our selection is the expression in an ExpressionStatement, expand
- // the selection to include the enclosing Statement (this stops us
- // from trying to care about the return value of the extracted function
- // and eliminates double semicolon insertion in certain scenarios)
- return ts.isExpressionStatement(node.parent) ? [node.parent] : node;
- }
- return undefined;
- }
- function isScope(node) {
- return ts.isFunctionLikeDeclaration(node) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node);
- }
- /**
- * Computes possible places we could extract the function into. For example,
- * you may be able to extract into a class method *or* local closure *or* namespace function,
- * depending on what's in the extracted body.
- */
- function collectEnclosingScopes(range) {
- var current = isReadonlyArray(range.range) ? ts.first(range.range) : range.range;
- if (range.facts & RangeFacts.UsesThis) {
- // if range uses this as keyword or as type inside the class then it can only be extracted to a method of the containing class
- var containingClass = ts.getContainingClass(current);
- if (containingClass) {
- var containingFunction = ts.findAncestor(current, ts.isFunctionLikeDeclaration);
- return containingFunction
- ? [containingFunction, containingClass]
- : [containingClass];
- }
- }
- var scopes = [];
- while (true) {
- current = current.parent;
- // A function parameter's initializer is actually in the outer scope, not the function declaration
- if (current.kind === 156 /* Parameter */) {
- // Skip all the way to the outer scope of the function that declared this parameter
- current = ts.findAncestor(current, function (parent) { return ts.isFunctionLikeDeclaration(parent); }).parent;
- }
- // We want to find the nearest parent where we can place an "equivalent" sibling to the node we're extracting out of.
- // Walk up to the closest parent of a place where we can logically put a sibling:
- // * Function declaration
- // * Class declaration or expression
- // * Module/namespace or source file
- if (isScope(current)) {
- scopes.push(current);
- if (current.kind === 290 /* SourceFile */) {
- return scopes;
- }
- }
- }
- }
- function getFunctionExtractionAtIndex(targetRange, context, requestedChangesIndex) {
- var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, functionErrorsPerScope = _b.functionErrorsPerScope, exposedVariableDeclarations = _b.exposedVariableDeclarations;
- ts.Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
- context.cancellationToken.throwIfCancellationRequested(); // TODO: GH#18217
- return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context);
- }
- function getConstantExtractionAtIndex(targetRange, context, requestedChangesIndex) {
- var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, constantErrorsPerScope = _b.constantErrorsPerScope, exposedVariableDeclarations = _b.exposedVariableDeclarations;
- ts.Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
- ts.Debug.assert(exposedVariableDeclarations.length === 0, "Extract constant accepted a range containing a variable declaration?");
- context.cancellationToken.throwIfCancellationRequested();
- var expression = ts.isExpression(target)
- ? target
- : target.statements[0].expression;
- return extractConstantInScope(expression, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange.facts, context);
- }
- /**
- * 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) {
- var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, functionErrorsPerScope = _b.functionErrorsPerScope, constantErrorsPerScope = _b.constantErrorsPerScope;
- // Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547
- var extractions = scopes.map(function (scope, i) {
- var functionDescriptionPart = getDescriptionForFunctionInScope(scope);
- var constantDescriptionPart = getDescriptionForConstantInScope(scope);
- var scopeDescription = ts.isFunctionLikeDeclaration(scope)
- ? getDescriptionForFunctionLikeDeclaration(scope)
- : ts.isClassLike(scope)
- ? getDescriptionForClassLikeDeclaration(scope)
- : getDescriptionForModuleLikeDeclaration(scope);
- var functionDescription;
- var constantDescription;
- if (scopeDescription === 1 /* Global */) {
- functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "global"]);
- constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "global"]);
- }
- else if (scopeDescription === 0 /* Module */) {
- functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "module"]);
- constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "module"]);
- }
- else {
- functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [functionDescriptionPart, scopeDescription]);
- constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [constantDescriptionPart, scopeDescription]);
- }
- // Customize the phrasing for the innermost scope to increase clarity.
- if (i === 0 && !ts.isClassLike(scope)) {
- constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_enclosing_scope), [constantDescriptionPart]);
- }
- return {
- functionExtraction: {
- description: functionDescription,
- errors: functionErrorsPerScope[i],
- },
- constantExtraction: {
- description: constantDescription,
- errors: constantErrorsPerScope[i],
- },
- };
- });
- return extractions;
- }
- function getPossibleExtractionsWorker(targetRange, context) {
- var sourceFile = context.file;
- var scopes = collectEnclosingScopes(targetRange);
- var enclosingTextRange = getEnclosingTextRange(targetRange, sourceFile);
- var readsAndWrites = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker(), context.cancellationToken);
- return { scopes: scopes, readsAndWrites: readsAndWrites };
- }
- function getDescriptionForFunctionInScope(scope) {
- return ts.isFunctionLikeDeclaration(scope)
- ? "inner function"
- : ts.isClassLike(scope)
- ? "method"
- : "function";
- }
- function getDescriptionForConstantInScope(scope) {
- return ts.isClassLike(scope)
- ? "readonly field"
- : "constant";
- }
- function getDescriptionForFunctionLikeDeclaration(scope) {
- switch (scope.kind) {
- case 162 /* Constructor */:
- return "constructor";
- case 201 /* FunctionExpression */:
- case 244 /* FunctionDeclaration */:
- return scope.name
- ? "function '" + scope.name.text + "'"
- : ts.ANONYMOUS;
- case 202 /* ArrowFunction */:
- return "arrow function";
- case 161 /* MethodDeclaration */:
- return "method '" + scope.name.getText() + "'";
- case 163 /* GetAccessor */:
- return "'get " + scope.name.getText() + "'";
- case 164 /* SetAccessor */:
- return "'set " + scope.name.getText() + "'";
- default:
- throw ts.Debug.assertNever(scope, "Unexpected scope kind " + scope.kind);
- }
- }
- function getDescriptionForClassLikeDeclaration(scope) {
- return scope.kind === 245 /* ClassDeclaration */
- ? scope.name ? "class '" + scope.name.text + "'" : "anonymous class declaration"
- : scope.name ? "class expression '" + scope.name.text + "'" : "anonymous class expression";
- }
- function getDescriptionForModuleLikeDeclaration(scope) {
- return scope.kind === 250 /* ModuleBlock */
- ? "namespace '" + scope.parent.name.getText() + "'"
- : scope.externalModuleIndicator ? 0 /* Module */ : 1 /* Global */;
- }
- var SpecialScope;
- (function (SpecialScope) {
- SpecialScope[SpecialScope["Module"] = 0] = "Module";
- SpecialScope[SpecialScope["Global"] = 1] = "Global";
- })(SpecialScope || (SpecialScope = {}));
- /**
- * 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, exposedVariableDeclarations, range, context) {
- var usagesInScope = _a.usages, typeParameterUsages = _a.typeParameterUsages, substitutions = _a.substitutions;
- var checker = context.program.getTypeChecker();
- var scriptTarget = ts.getEmitScriptTarget(context.program.getCompilerOptions());
- var importAdder = ts.codefix.createImportAdder(context.file, context.program, context.preferences, context.host);
- // Make a unique name for the extracted function
- var file = scope.getSourceFile();
- var functionNameText = ts.getUniqueName(ts.isClassLike(scope) ? "newMethod" : "newFunction", file);
- var isJS = ts.isInJSFile(scope);
- var functionName = ts.createIdentifier(functionNameText);
- var returnType;
- var parameters = [];
- var callArguments = [];
- var writes;
- usagesInScope.forEach(function (usage, name) {
- var typeNode;
- if (!isJS) {
- var type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node);
- // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {"
- type = checker.getBaseTypeOfLiteralType(type);
- typeNode = ts.codefix.typeToAutoImportableTypeNode(checker, importAdder, type, scope, scriptTarget, 1 /* NoTruncation */);
- }
- var paramDecl = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- /*dotDotDotToken*/ undefined,
- /*name*/ name,
- /*questionToken*/ undefined, typeNode);
- parameters.push(paramDecl);
- if (usage.usage === 2 /* Write */) {
- (writes || (writes = [])).push(usage);
- }
- callArguments.push(ts.createIdentifier(name));
- });
- var typeParametersAndDeclarations = ts.arrayFrom(typeParameterUsages.values()).map(function (type) { return ({ type: type, declaration: getFirstDeclaration(type) }); });
- var sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder);
- var typeParameters = sortedTypeParametersAndDeclarations.length === 0
- ? undefined
- : sortedTypeParametersAndDeclarations.map(function (t) { return t.declaration; });
- // Strictly speaking, we should check whether each name actually binds to the appropriate type
- // parameter. In cases of shadowing, they may not.
- var callTypeArguments = typeParameters !== undefined
- ? typeParameters.map(function (decl) { return ts.createTypeReferenceNode(decl.name, /*typeArguments*/ undefined); })
- : undefined;
- // Provide explicit return types for contextually-typed functions
- // to avoid problems when there are literal types present
- if (ts.isExpression(node) && !isJS) {
- var contextualType = checker.getContextualType(node);
- returnType = checker.typeToTypeNode(contextualType, scope, 1 /* NoTruncation */); // TODO: GH#18217
- }
- var _b = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty;
- ts.suppressLeadingAndTrailingTrivia(body);
- var newFunction;
- if (ts.isClassLike(scope)) {
- // always create private method in TypeScript files
- var modifiers = isJS ? [] : [ts.createToken(117 /* PrivateKeyword */)];
- if (range.facts & RangeFacts.InStaticRegion) {
- modifiers.push(ts.createToken(120 /* StaticKeyword */));
- }
- if (range.facts & RangeFacts.IsAsyncFunction) {
- modifiers.push(ts.createToken(126 /* AsyncKeyword */));
- }
- newFunction = ts.createMethod(
- /*decorators*/ undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(41 /* AsteriskToken */) : undefined, functionName,
- /*questionToken*/ undefined, typeParameters, parameters, returnType, body);
- }
- else {
- newFunction = ts.createFunctionDeclaration(
- /*decorators*/ undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.createToken(126 /* AsyncKeyword */)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(41 /* AsteriskToken */) : undefined, functionName, typeParameters, parameters, returnType, body);
- }
- var changeTracker = ts.textChanges.ChangeTracker.fromContext(context);
- var minInsertionPos = (isReadonlyArray(range.range) ? ts.last(range.range) : range.range).end;
- var nodeToInsertBefore = getNodeToInsertFunctionBefore(minInsertionPos, scope);
- if (nodeToInsertBefore) {
- changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, /*blankLineBetween*/ true);
- }
- else {
- changeTracker.insertNodeAtEndOfScope(context.file, scope, newFunction);
- }
- importAdder.writeFixes(changeTracker);
- var newNodes = [];
- // replace range with function call
- var called = getCalledExpression(scope, range, functionNameText);
- var call = ts.createCall(called, callTypeArguments, // Note that no attempt is made to take advantage of type argument inference
- callArguments);
- if (range.facts & RangeFacts.IsGenerator) {
- call = ts.createYield(ts.createToken(41 /* AsteriskToken */), call);
- }
- if (range.facts & RangeFacts.IsAsyncFunction) {
- call = ts.createAwait(call);
- }
- if (exposedVariableDeclarations.length && !writes) {
- // No need to mix declarations and writes.
- // How could any variables be exposed if there's a return statement?
- ts.Debug.assert(!returnValueProperty, "Expected no returnValueProperty");
- ts.Debug.assert(!(range.facts & RangeFacts.HasReturn), "Expected RangeFacts.HasReturn flag to be unset");
- if (exposedVariableDeclarations.length === 1) {
- // Declaring exactly one variable: let x = newFunction();
- var variableDeclaration = exposedVariableDeclarations[0];
- newNodes.push(ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.getSynthesizedDeepClone(variableDeclaration.name), /*type*/ ts.getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns
- variableDeclaration.parent.flags)));
- }
- else {
- // Declaring multiple variables / return properties:
- // let {x, y} = newFunction();
- var bindingElements = [];
- var typeElements = [];
- var commonNodeFlags = exposedVariableDeclarations[0].parent.flags;
- var sawExplicitType = false;
- for (var _i = 0, exposedVariableDeclarations_1 = exposedVariableDeclarations; _i < exposedVariableDeclarations_1.length; _i++) {
- var variableDeclaration = exposedVariableDeclarations_1[_i];
- bindingElements.push(ts.createBindingElement(
- /*dotDotDotToken*/ undefined,
- /*propertyName*/ undefined,
- /*name*/ ts.getSynthesizedDeepClone(variableDeclaration.name)));
- // Being returned through an object literal will have widened the type.
- var variableType = checker.typeToTypeNode(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), scope, 1 /* NoTruncation */);
- typeElements.push(ts.createPropertySignature(
- /*modifiers*/ undefined,
- /*name*/ variableDeclaration.symbol.name,
- /*questionToken*/ undefined,
- /*type*/ variableType,
- /*initializer*/ undefined));
- sawExplicitType = sawExplicitType || variableDeclaration.type !== undefined;
- commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags;
- }
- var typeLiteral = sawExplicitType ? ts.createTypeLiteralNode(typeElements) : undefined;
- if (typeLiteral) {
- ts.setEmitFlags(typeLiteral, 1 /* SingleLine */);
- }
- newNodes.push(ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createObjectBindingPattern(bindingElements),
- /*type*/ typeLiteral,
- /*initializer*/ call)], commonNodeFlags)));
- }
- }
- else if (exposedVariableDeclarations.length || writes) {
- if (exposedVariableDeclarations.length) {
- // CONSIDER: we're going to create one statement per variable, but we could actually preserve their original grouping.
- for (var _c = 0, exposedVariableDeclarations_2 = exposedVariableDeclarations; _c < exposedVariableDeclarations_2.length; _c++) {
- var variableDeclaration = exposedVariableDeclarations_2[_c];
- var flags = variableDeclaration.parent.flags;
- if (flags & 2 /* Const */) {
- flags = (flags & ~2 /* Const */) | 1 /* Let */;
- }
- newNodes.push(ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags)));
- }
- }
- if (returnValueProperty) {
- // has both writes and return, need to create variable declaration to hold return value;
- newNodes.push(ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(returnValueProperty, getTypeDeepCloneUnionUndefined(returnType))], 1 /* Let */)));
- }
- var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes);
- if (returnValueProperty) {
- assignments.unshift(ts.createShorthandPropertyAssignment(returnValueProperty));
- }
- // propagate writes back
- if (assignments.length === 1) {
- // We would only have introduced a return value property if there had been
- // other assignments to make.
- ts.Debug.assert(!returnValueProperty, "Shouldn't have returnValueProperty here");
- newNodes.push(ts.createStatement(ts.createAssignment(assignments[0].name, call)));
- if (range.facts & RangeFacts.HasReturn) {
- newNodes.push(ts.createReturn());
- }
- }
- else {
- // emit e.g.
- // { a, b, __return } = newFunction(a, b);
- // return __return;
- newNodes.push(ts.createStatement(ts.createAssignment(ts.createObjectLiteral(assignments), call)));
- if (returnValueProperty) {
- newNodes.push(ts.createReturn(ts.createIdentifier(returnValueProperty)));
- }
- }
- }
- else {
- if (range.facts & RangeFacts.HasReturn) {
- newNodes.push(ts.createReturn(call));
- }
- else if (isReadonlyArray(range.range)) {
- newNodes.push(ts.createStatement(call));
- }
- else {
- newNodes.push(call);
- }
- }
- if (isReadonlyArray(range.range)) {
- changeTracker.replaceNodeRangeWithNodes(context.file, ts.first(range.range), ts.last(range.range), newNodes);
- }
- else {
- changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes);
- }
- var edits = changeTracker.getChanges();
- var renameRange = isReadonlyArray(range.range) ? ts.first(range.range) : range.range;
- var renameFilename = renameRange.getSourceFile().fileName;
- var renameLocation = ts.getRenameLocation(edits, renameFilename, functionNameText, /*isDeclaredBeforeUse*/ false);
- return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits };
- function getTypeDeepCloneUnionUndefined(typeNode) {
- if (typeNode === undefined) {
- return undefined;
- }
- var clone = ts.getSynthesizedDeepClone(typeNode);
- var withoutParens = clone;
- while (ts.isParenthesizedTypeNode(withoutParens)) {
- withoutParens = withoutParens.type;
- }
- return ts.isUnionTypeNode(withoutParens) && ts.find(withoutParens.types, function (t) { return t.kind === 146 /* UndefinedKeyword */; })
- ? clone
- : ts.createUnionTypeNode([clone, ts.createKeywordTypeNode(146 /* UndefinedKeyword */)]);
- }
- }
- /**
- * 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 extractConstantInScope(node, scope, _a, rangeFacts, context) {
- var _b;
- var substitutions = _a.substitutions;
- var checker = context.program.getTypeChecker();
- // Make a unique name for the extracted variable
- var file = scope.getSourceFile();
- var localNameText = ts.getUniqueName(ts.isClassLike(scope) ? "newProperty" : "newLocal", file);
- var isJS = ts.isInJSFile(scope);
- var variableType = isJS || !checker.isContextSensitive(node)
- ? undefined
- : checker.typeToTypeNode(checker.getContextualType(node), scope, 1 /* NoTruncation */); // TODO: GH#18217
- var initializer = transformConstantInitializer(node, substitutions);
- (_b = transformFunctionInitializerAndType(variableType, initializer), variableType = _b.variableType, initializer = _b.initializer);
- ts.suppressLeadingAndTrailingTrivia(initializer);
- var changeTracker = ts.textChanges.ChangeTracker.fromContext(context);
- if (ts.isClassLike(scope)) {
- ts.Debug.assert(!isJS, "Cannot extract to a JS class"); // See CannotExtractToJSClass
- var modifiers = [];
- modifiers.push(ts.createToken(117 /* PrivateKeyword */));
- if (rangeFacts & RangeFacts.InStaticRegion) {
- modifiers.push(ts.createToken(120 /* StaticKeyword */));
- }
- modifiers.push(ts.createToken(138 /* ReadonlyKeyword */));
- var newVariable = ts.createProperty(
- /*decorators*/ undefined, modifiers, localNameText,
- /*questionToken*/ undefined, variableType, initializer);
- var localReference = ts.createPropertyAccess(rangeFacts & RangeFacts.InStaticRegion
- ? ts.createIdentifier(scope.name.getText()) // TODO: GH#18217
- : ts.createThis(), ts.createIdentifier(localNameText));
- // Declare
- var maxInsertionPos = node.pos;
- var nodeToInsertBefore = getNodeToInsertPropertyBefore(maxInsertionPos, scope);
- changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, /*blankLineBetween*/ true);
- // Consume
- changeTracker.replaceNode(context.file, node, localReference);
- }
- else {
- var newVariableDeclaration = ts.createVariableDeclaration(localNameText, variableType, initializer);
- // If the node is part of an initializer in a list of variable declarations, insert a new
- // variable declaration into the list (in case it depends on earlier ones).
- // CONSIDER: If the declaration list isn't const, we might want to split it into multiple
- // lists so that the newly extracted one can be const.
- var oldVariableDeclaration = getContainingVariableDeclarationIfInList(node, scope);
- if (oldVariableDeclaration) {
- // Declare
- // CONSIDER: could detect that each is on a separate line (See `extractConstant_VariableList_MultipleLines` in `extractConstants.ts`)
- changeTracker.insertNodeBefore(context.file, oldVariableDeclaration, newVariableDeclaration);
- // Consume
- var localReference = ts.createIdentifier(localNameText);
- changeTracker.replaceNode(context.file, node, localReference);
- }
- else if (node.parent.kind === 226 /* ExpressionStatement */ && scope === ts.findAncestor(node, isScope)) {
- // If the parent is an expression statement and the target scope is the immediately enclosing one,
- // replace the statement with the declaration.
- var newVariableStatement = ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2 /* Const */));
- changeTracker.replaceNode(context.file, node.parent, newVariableStatement);
- }
- else {
- var newVariableStatement = ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2 /* Const */));
- // Declare
- var nodeToInsertBefore = getNodeToInsertConstantBefore(node, scope);
- if (nodeToInsertBefore.pos === 0) {
- changeTracker.insertNodeAtTopOfFile(context.file, newVariableStatement, /*blankLineBetween*/ false);
- }
- else {
- changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariableStatement, /*blankLineBetween*/ false);
- }
- // Consume
- if (node.parent.kind === 226 /* ExpressionStatement */) {
- // If the parent is an expression statement, delete it.
- changeTracker.delete(context.file, node.parent);
- }
- else {
- var localReference = ts.createIdentifier(localNameText);
- changeTracker.replaceNode(context.file, node, localReference);
- }
- }
- }
- var edits = changeTracker.getChanges();
- var renameFilename = node.getSourceFile().fileName;
- var renameLocation = ts.getRenameLocation(edits, renameFilename, localNameText, /*isDeclaredBeforeUse*/ true);
- return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits };
- function transformFunctionInitializerAndType(variableType, initializer) {
- // If no contextual type exists there is nothing to transfer to the function signature
- if (variableType === undefined)
- return { variableType: variableType, initializer: initializer };
- // Only do this for function expressions and arrow functions that are not generic
- if (!ts.isFunctionExpression(initializer) && !ts.isArrowFunction(initializer) || !!initializer.typeParameters)
- return { variableType: variableType, initializer: initializer };
- var functionType = checker.getTypeAtLocation(node);
- var functionSignature = ts.singleOrUndefined(checker.getSignaturesOfType(functionType, 0 /* Call */));
- // If no function signature, maybe there was an error, do nothing
- if (!functionSignature)
- return { variableType: variableType, initializer: initializer };
- // If the function signature has generic type parameters we don't attempt to move the parameters
- if (!!functionSignature.getTypeParameters())
- return { variableType: variableType, initializer: initializer };
- // We add parameter types if needed
- var parameters = [];
- var hasAny = false;
- for (var _i = 0, _a = initializer.parameters; _i < _a.length; _i++) {
- var p = _a[_i];
- if (p.type) {
- parameters.push(p);
- }
- else {
- var paramType = checker.getTypeAtLocation(p);
- if (paramType === checker.getAnyType())
- hasAny = true;
- parameters.push(ts.updateParameter(p, p.decorators, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, p.type || checker.typeToTypeNode(paramType, scope, 1 /* NoTruncation */), p.initializer));
- }
- }
- // If a parameter was inferred as any we skip adding function parameters at all.
- // Turning an implicit any (which under common settings is a error) to an explicit
- // is probably actually a worse refactor outcome.
- if (hasAny)
- return { variableType: variableType, initializer: initializer };
- variableType = undefined;
- if (ts.isArrowFunction(initializer)) {
- initializer = ts.updateArrowFunction(initializer, node.modifiers, initializer.typeParameters, parameters, initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, 1 /* NoTruncation */), initializer.equalsGreaterThanToken, initializer.body);
- }
- else {
- if (functionSignature && !!functionSignature.thisParameter) {
- var firstParameter = ts.firstOrUndefined(parameters);
- // If the function signature has a this parameter and if the first defined parameter is not the this parameter, we must add it
- // Note: If this parameter was already there, it would have been previously updated with the type if not type was present
- if ((!firstParameter || (ts.isIdentifier(firstParameter.name) && firstParameter.name.escapedText !== "this"))) {
- var thisType = checker.getTypeOfSymbolAtLocation(functionSignature.thisParameter, node);
- parameters.splice(0, 0, ts.createParameter(
- /* decorators */ undefined,
- /* modifiers */ undefined,
- /* dotDotDotToken */ undefined, "this",
- /* questionToken */ undefined, checker.typeToTypeNode(thisType, scope, 1 /* NoTruncation */)));
- }
- }
- initializer = ts.updateFunctionExpression(initializer, node.modifiers, initializer.asteriskToken, initializer.name, initializer.typeParameters, parameters, initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, 1 /* NoTruncation */), initializer.body);
- }
- return { variableType: variableType, initializer: initializer };
- }
- }
- function getContainingVariableDeclarationIfInList(node, scope) {
- var prevNode;
- while (node !== undefined && node !== scope) {
- if (ts.isVariableDeclaration(node) &&
- node.initializer === prevNode &&
- ts.isVariableDeclarationList(node.parent) &&
- node.parent.declarations.length > 1) {
- return node;
- }
- prevNode = node;
- node = node.parent;
- }
- }
- function getFirstDeclaration(type) {
- var firstDeclaration;
- var symbol = type.symbol;
- if (symbol && symbol.declarations) {
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (firstDeclaration === undefined || declaration.pos < firstDeclaration.pos) {
- firstDeclaration = declaration;
- }
- }
- }
- return firstDeclaration;
- }
- function compareTypesByDeclarationOrder(_a, _b) {
- var type1 = _a.type, declaration1 = _a.declaration;
- var type2 = _b.type, declaration2 = _b.declaration;
- return ts.compareProperties(declaration1, declaration2, "pos", ts.compareValues)
- || ts.compareStringsCaseSensitive(type1.symbol ? type1.symbol.getName() : "", type2.symbol ? type2.symbol.getName() : "")
- || ts.compareValues(type1.id, type2.id);
- }
- 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(); // TODO: GH#18217
- return ts.createPropertyAccess(lhs, functionReference);
- }
- else {
- return functionReference;
- }
- }
- function transformFunctionBody(body, exposedVariableDeclarations, writes, substitutions, hasReturn) {
- var hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0;
- if (ts.isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) {
- // already block, no declarations or writes to propagate back, no substitutions - can use node as is
- return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
- }
- var returnValueProperty;
- var ignoreReturns = false;
- 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 (hasWritesOrVariableDeclarations || substitutions.size) {
- var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
- if (hasWritesOrVariableDeclarations && !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 = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes);
- if (assignments.length === 1) {
- rewrittenStatements.push(ts.createReturn(assignments[0].name));
- }
- else {
- 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 (!ignoreReturns && node.kind === 235 /* ReturnStatement */ && hasWritesOrVariableDeclarations) {
- var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, 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 oldIgnoreReturns = ignoreReturns;
- ignoreReturns = ignoreReturns || ts.isFunctionLikeDeclaration(node) || ts.isClassLike(node);
- var substitution = substitutions.get(ts.getNodeId(node).toString());
- var result = substitution ? ts.getSynthesizedDeepClone(substitution) : ts.visitEachChild(node, visitor, ts.nullTransformationContext);
- ignoreReturns = oldIgnoreReturns;
- return result;
- }
- }
- }
- function transformConstantInitializer(initializer, substitutions) {
- return substitutions.size
- ? visitor(initializer)
- : initializer;
- function visitor(node) {
- var substitution = substitutions.get(ts.getNodeId(node).toString());
- return substitution ? ts.getSynthesizedDeepClone(substitution) : ts.visitEachChild(node, visitor, ts.nullTransformationContext);
- }
- }
- function getStatementsOrClassElements(scope) {
- if (ts.isFunctionLikeDeclaration(scope)) {
- var body = scope.body; // TODO: GH#18217
- if (ts.isBlock(body)) {
- return body.statements;
- }
- }
- else if (ts.isModuleBlock(scope) || ts.isSourceFile(scope)) {
- return scope.statements;
- }
- else if (ts.isClassLike(scope)) {
- return scope.members;
- }
- else {
- ts.assertType(scope);
- }
- return ts.emptyArray;
- }
- /**
- * If `scope` contains a function after `minPos`, then return the first such function.
- * Otherwise, return `undefined`.
- */
- function getNodeToInsertFunctionBefore(minPos, scope) {
- return ts.find(getStatementsOrClassElements(scope), function (child) {
- return child.pos >= minPos && ts.isFunctionLikeDeclaration(child) && !ts.isConstructorDeclaration(child);
- });
- }
- function getNodeToInsertPropertyBefore(maxPos, scope) {
- var members = scope.members;
- ts.Debug.assert(members.length > 0, "Found no members"); // There must be at least one child, since we extracted from one.
- var prevMember;
- var allProperties = true;
- for (var _i = 0, members_1 = members; _i < members_1.length; _i++) {
- var member = members_1[_i];
- if (member.pos > maxPos) {
- return prevMember || members[0];
- }
- if (allProperties && !ts.isPropertyDeclaration(member)) {
- // If it is non-vacuously true that all preceding members are properties,
- // insert before the current member (i.e. at the end of the list of properties).
- if (prevMember !== undefined) {
- return member;
- }
- allProperties = false;
- }
- prevMember = member;
- }
- if (prevMember === undefined)
- return ts.Debug.fail(); // If the loop didn't return, then it did set prevMember.
- return prevMember;
- }
- function getNodeToInsertConstantBefore(node, scope) {
- ts.Debug.assert(!ts.isClassLike(scope));
- var prevScope;
- for (var curr = node; curr !== scope; curr = curr.parent) {
- if (isScope(curr)) {
- prevScope = curr;
- }
- }
- for (var curr = (prevScope || node).parent;; curr = curr.parent) {
- if (isBlockLike(curr)) {
- var prevStatement = void 0;
- for (var _i = 0, _a = curr.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- if (statement.pos > node.pos) {
- break;
- }
- prevStatement = statement;
- }
- if (!prevStatement && ts.isCaseClause(curr)) {
- // We must have been in the expression of the case clause.
- ts.Debug.assert(ts.isSwitchStatement(curr.parent.parent), "Grandparent isn't a switch statement");
- return curr.parent.parent;
- }
- // There must be at least one statement since we started in one.
- return ts.Debug.checkDefined(prevStatement, "prevStatement failed to get set");
- }
- ts.Debug.assert(curr !== scope, "Didn't encounter a block-like before encountering scope");
- }
- }
- function getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes) {
- var variableAssignments = ts.map(exposedVariableDeclarations, function (v) { return ts.createShorthandPropertyAssignment(v.symbol.name); });
- var writeAssignments = ts.map(writes, function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
- // TODO: GH#18217 `variableAssignments` not possibly undefined!
- return variableAssignments === undefined
- ? writeAssignments
- : writeAssignments === undefined
- ? variableAssignments
- : variableAssignments.concat(writeAssignments);
- }
- function isReadonlyArray(v) {
- return ts.isArray(v);
- }
- /**
- * Produces a range that spans the entirety of nodes, given a selection
- * that might start/end in the middle of nodes.
- *
- * For example, when the user makes a selection like this
- * v---v
- * var someThing = foo + bar;
- * this returns ^-------^
- */
- function getEnclosingTextRange(targetRange, sourceFile) {
- return isReadonlyArray(targetRange.range)
- ? { pos: ts.first(targetRange.range).getStart(sourceFile), end: ts.last(targetRange.range).getEnd() }
- : targetRange.range;
- }
- var Usage;
- (function (Usage) {
- // value should be passed to extracted method
- Usage[Usage["Read"] = 1] = "Read";
- // value should be passed to extracted method and propagated back
- Usage[Usage["Write"] = 2] = "Write";
- })(Usage || (Usage = {}));
- function collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, checker, cancellationToken) {
- var allTypeParameterUsages = ts.createMap(); // Key is type ID
- var usagesPerScope = [];
- var substitutionsPerScope = [];
- var functionErrorsPerScope = [];
- var constantErrorsPerScope = [];
- var visibleDeclarationsInExtractedRange = [];
- var exposedVariableSymbolSet = ts.createMap(); // Key is symbol ID
- var exposedVariableDeclarations = [];
- var firstExposedNonVariableDeclaration;
- var expression = !isReadonlyArray(targetRange.range)
- ? targetRange.range
- : targetRange.range.length === 1 && ts.isExpressionStatement(targetRange.range[0])
- ? targetRange.range[0].expression
- : undefined;
- var expressionDiagnostic;
- if (expression === undefined) {
- var statements = targetRange.range;
- var start = ts.first(statements).getStart();
- var end = ts.last(statements).end;
- expressionDiagnostic = ts.createFileDiagnostic(sourceFile, start, end - start, Messages.expressionExpected);
- }
- else if (checker.getTypeAtLocation(expression).flags & (16384 /* Void */ | 131072 /* Never */)) {
- expressionDiagnostic = ts.createDiagnosticForNode(expression, Messages.uselessConstantType);
- }
- // initialize results
- for (var _i = 0, scopes_1 = scopes; _i < scopes_1.length; _i++) {
- var scope = scopes_1[_i];
- usagesPerScope.push({ usages: ts.createMap(), typeParameterUsages: ts.createMap(), substitutions: ts.createMap() });
- substitutionsPerScope.push(ts.createMap());
- functionErrorsPerScope.push(ts.isFunctionLikeDeclaration(scope) && scope.kind !== 244 /* FunctionDeclaration */
- ? [ts.createDiagnosticForNode(scope, Messages.cannotExtractToOtherFunctionLike)]
- : []);
- var constantErrors = [];
- if (expressionDiagnostic) {
- constantErrors.push(expressionDiagnostic);
- }
- if (ts.isClassLike(scope) && ts.isInJSFile(scope)) {
- constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToJSClass));
- }
- if (ts.isArrowFunction(scope) && !ts.isBlock(scope.body)) {
- // TODO (https://github.com/Microsoft/TypeScript/issues/18924): allow this
- constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToExpressionArrowFunction));
- }
- constantErrorsPerScope.push(constantErrors);
- }
- var seenUsages = ts.createMap();
- var target = isReadonlyArray(targetRange.range) ? ts.createBlock(targetRange.range) : targetRange.range;
- var unmodifiedNode = isReadonlyArray(targetRange.range) ? ts.first(targetRange.range) : targetRange.range;
- var inGenericContext = isInGenericContext(unmodifiedNode);
- collectUsages(target);
- // Unfortunately, this code takes advantage of the knowledge that the generated method
- // will use the contextual type of an expression as the return type of the extracted
- // method (and will therefore "use" all the types involved).
- if (inGenericContext && !isReadonlyArray(targetRange.range)) {
- var contextualType = checker.getContextualType(targetRange.range); // TODO: GH#18217
- recordTypeParameterUsages(contextualType);
- }
- if (allTypeParameterUsages.size > 0) {
- var seenTypeParameterUsages = ts.createMap(); // Key is type ID
- var i_1 = 0;
- for (var curr = unmodifiedNode; curr !== undefined && i_1 < scopes.length; curr = curr.parent) {
- if (curr === scopes[i_1]) {
- // Copy current contents of seenTypeParameterUsages into scope.
- seenTypeParameterUsages.forEach(function (typeParameter, id) {
- usagesPerScope[i_1].typeParameterUsages.set(id, typeParameter);
- });
- i_1++;
- }
- // Note that we add the current node's type parameters *after* updating the corresponding scope.
- if (ts.isDeclarationWithTypeParameters(curr)) {
- for (var _a = 0, _b = ts.getEffectiveTypeParameterDeclarations(curr); _a < _b.length; _a++) {
- var typeParameterDecl = _b[_a];
- var typeParameter = checker.getTypeAtLocation(typeParameterDecl);
- if (allTypeParameterUsages.has(typeParameter.id.toString())) {
- seenTypeParameterUsages.set(typeParameter.id.toString(), typeParameter);
- }
- }
- }
- }
- // If we didn't get through all the scopes, then there were some that weren't in our
- // parent chain (impossible at time of writing). A conservative solution would be to
- // copy allTypeParameterUsages into all remaining scopes.
- ts.Debug.assert(i_1 === scopes.length, "Should have iterated all scopes");
- }
- // If there are any declarations in the extracted block that are used in the same enclosing
- // lexical scope, we can't move the extraction "up" as those declarations will become unreachable
- if (visibleDeclarationsInExtractedRange.length) {
- var containingLexicalScopeOfExtraction = ts.isBlockScope(scopes[0], scopes[0].parent)
- ? scopes[0]
- : ts.getEnclosingBlockScopeContainer(scopes[0]);
- ts.forEachChild(containingLexicalScopeOfExtraction, checkForUsedDeclarations);
- }
- var _loop_16 = function (i) {
- var scopeUsages = usagesPerScope[i];
- // Special case: in the innermost scope, all usages are available.
- // (The computed value reflects the value at the top-level of the scope, but the
- // local will actually be declared at the same level as the extracted expression).
- if (i > 0 && (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0)) {
- var errorNode = isReadonlyArray(targetRange.range) ? targetRange.range[0] : targetRange.range;
- constantErrorsPerScope[i].push(ts.createDiagnosticForNode(errorNode, Messages.cannotAccessVariablesFromNestedScopes));
- }
- var hasWrite = false;
- var readonlyClassPropertyWrite;
- usagesPerScope[i].usages.forEach(function (value) {
- if (value.usage === 2 /* Write */) {
- hasWrite = true;
- if (value.symbol.flags & 106500 /* ClassMember */ &&
- value.symbol.valueDeclaration &&
- ts.hasModifier(value.symbol.valueDeclaration, 64 /* Readonly */)) {
- readonlyClassPropertyWrite = value.symbol.valueDeclaration;
- }
- }
- });
- // If an expression was extracted, then there shouldn't have been any variable declarations.
- ts.Debug.assert(isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0, "No variable declarations expected if something was extracted");
- if (hasWrite && !isReadonlyArray(targetRange.range)) {
- var diag = ts.createDiagnosticForNode(targetRange.range, Messages.cannotWriteInExpression);
- functionErrorsPerScope[i].push(diag);
- constantErrorsPerScope[i].push(diag);
- }
- else if (readonlyClassPropertyWrite && i > 0) {
- var diag = ts.createDiagnosticForNode(readonlyClassPropertyWrite, Messages.cannotExtractReadonlyPropertyInitializerOutsideConstructor);
- functionErrorsPerScope[i].push(diag);
- constantErrorsPerScope[i].push(diag);
- }
- else if (firstExposedNonVariableDeclaration) {
- var diag = ts.createDiagnosticForNode(firstExposedNonVariableDeclaration, Messages.cannotExtractExportedEntity);
- functionErrorsPerScope[i].push(diag);
- constantErrorsPerScope[i].push(diag);
- }
- };
- for (var i = 0; i < scopes.length; i++) {
- _loop_16(i);
- }
- return { target: target, usagesPerScope: usagesPerScope, functionErrorsPerScope: functionErrorsPerScope, constantErrorsPerScope: constantErrorsPerScope, exposedVariableDeclarations: exposedVariableDeclarations };
- function isInGenericContext(node) {
- return !!ts.findAncestor(node, function (n) { return ts.isDeclarationWithTypeParameters(n) && ts.getEffectiveTypeParameterDeclarations(n).length !== 0; });
- }
- function recordTypeParameterUsages(type) {
- // PERF: This is potentially very expensive. `type` could be a library type with
- // a lot of properties, each of which the walker will visit. Unfortunately, the
- // solution isn't as trivial as filtering to user types because of (e.g.) Array.
- var symbolWalker = checker.getSymbolWalker(function () { return (cancellationToken.throwIfCancellationRequested(), true); });
- var visitedTypes = symbolWalker.walkType(type).visitedTypes;
- for (var _i = 0, visitedTypes_1 = visitedTypes; _i < visitedTypes_1.length; _i++) {
- var visitedType = visitedTypes_1[_i];
- if (visitedType.isTypeParameter()) {
- allTypeParameterUsages.set(visitedType.id.toString(), visitedType);
- }
- }
- }
- function collectUsages(node, valueUsage) {
- if (valueUsage === void 0) { valueUsage = 1 /* Read */; }
- if (inGenericContext) {
- var type = checker.getTypeAtLocation(node);
- recordTypeParameterUsages(type);
- }
- if (ts.isDeclaration(node) && node.symbol) {
- visibleDeclarationsInExtractedRange.push(node);
- }
- if (ts.isAssignmentExpression(node)) {
- // use 'write' as default usage for values
- collectUsages(node.left, 2 /* Write */);
- collectUsages(node.right);
- }
- else if (ts.isUnaryExpressionWithWrite(node)) {
- collectUsages(node.operand, 2 /* Write */);
- }
- else if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {
- // use 'write' as default usage for values
- ts.forEachChild(node, collectUsages);
- }
- else if (ts.isIdentifier(node)) {
- if (!node.parent) {
- return;
- }
- if (ts.isQualifiedName(node.parent) && node !== node.parent.left) {
- return;
- }
- if (ts.isPropertyAccessExpression(node.parent) && node !== node.parent.expression) {
- return;
- }
- recordUsage(node, valueUsage, /*isTypeNode*/ ts.isPartOfTypeNode(node));
- }
- else {
- ts.forEachChild(node, collectUsages);
- }
- }
- function recordUsage(n, usage, isTypeNode) {
- var symbolId = recordUsagebySymbol(n, usage, isTypeNode);
- if (symbolId) {
- for (var i = 0; i < scopes.length; i++) {
- // push substitution from map