ic */)) { continue; } var existingName = ts.getPropertyNameForPropertyNameNode(m.name); if (existingName) { existingMemberNames.add(existingName); } } return baseSymbols.filter(function (propertySymbol) { return !existingMemberNames.has(propertySymbol.escapedName) && !!propertySymbol.declarations && !(ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & 8 /* ModifierFlags.Private */) && !(propertySymbol.valueDeclaration && ts.isPrivateIdentifierClassElementDeclaration(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 = new ts.Set(); var membersDeclaredBySpreadAssignment = new ts.Set(); 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 === 285 /* SyntaxKind.JsxAttribute */) { seenNames.add(attr.name.escapedText); } else if (ts.isJsxSpreadAttribute(attr)) { setMembersDeclaredBySpreadAssignment(attr, membersDeclaredBySpreadAssignment); } } var filteredSymbols = symbols.filter(function (a) { return !seenNames.has(a.escapedName); }); setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, filteredSymbols); return filteredSymbols; } function isCurrentlyEditingNode(node) { return node.getStart(sourceFile) <= position && position <= node.getEnd(); } } /** * 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 /* SyntaxKind.OpenBraceToken */: // const x = { | case 27 /* SyntaxKind.CommaToken */: // const x = { a: 0, | if (ts.isObjectLiteralExpression(parent) || ts.isObjectBindingPattern(parent)) { return parent; } break; case 41 /* SyntaxKind.AsteriskToken */: return ts.isMethodDeclaration(parent) ? ts.tryCast(parent.parent, ts.isObjectLiteralExpression) : undefined; case 79 /* SyntaxKind.Identifier */: return contextToken.text === "async" && ts.isShorthandPropertyAssignment(contextToken.parent) ? contextToken.parent.parent : undefined; } } return undefined; } function getRelevantTokens(position, sourceFile) { var previousToken = ts.findPrecedingToken(position, sourceFile); if (previousToken && position <= previousToken.end && (ts.isMemberName(previousToken) || ts.isKeyword(previousToken.kind))) { var contextToken = ts.findPrecedingToken(previousToken.getFullStart(), sourceFile, /*startNode*/ undefined); // TODO: GH#18217 return { contextToken: contextToken, previousToken: previousToken }; } return { contextToken: previousToken, previousToken: previousToken }; } function getAutoImportSymbolFromCompletionEntryData(name, data, program, host) { var containingProgram = data.isPackageJsonImport ? host.getPackageJsonAutoImportProvider() : program; var checker = containingProgram.getTypeChecker(); var moduleSymbol = data.ambientModuleName ? checker.tryFindAmbientModule(data.ambientModuleName) : data.fileName ? checker.getMergedSymbol(ts.Debug.checkDefined(containingProgram.getSourceFile(data.fileName)).symbol) : undefined; if (!moduleSymbol) return undefined; var symbol = data.exportName === "export=" /* InternalSymbolName.ExportEquals */ ? checker.resolveExternalModuleSymbol(moduleSymbol) : checker.tryGetMemberInModuleExportsAndProperties(data.exportName, moduleSymbol); if (!symbol) return undefined; var isDefaultExport = data.exportName === "default" /* InternalSymbolName.Default */; symbol = isDefaultExport && ts.getLocalSymbolForExportDefault(symbol) || symbol; return { symbol: symbol, origin: completionEntryDataToSymbolOriginInfo(data, name, moduleSymbol) }; } function getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind, jsxIdentifierExpected) { var name = originIncludesSymbolName(origin) ? origin.symbolName : 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 /* SymbolFlags.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 /* LanguageVariant.JSX */ : 0 /* LanguageVariant.Standard */) || symbol.valueDeclaration && ts.isPrivateIdentifierClassElementDeclaration(symbol.valueDeclaration)) { return validNameResult; } switch (kind) { case 3 /* CompletionKind.MemberLike */: return undefined; case 0 /* CompletionKind.ObjectPropertyDeclaration */: // TODO: GH#18169 return { name: JSON.stringify(name), needsConvertPropertyAccess: false }; case 2 /* CompletionKind.PropertyAccess */: case 1 /* CompletionKind.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 /* CharacterCodes.space */ ? undefined : { name: name, needsConvertPropertyAccess: true }; case 5 /* CompletionKind.None */: case 4 /* CompletionKind.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 = 81 /* SyntaxKind.FirstKeyword */; i <= 160 /* SyntaxKind.LastKeyword */; i++) { res.push({ name: ts.tokenToString(i), kind: "keyword" /* ScriptElementKind.keyword */, kindModifiers: "" /* ScriptElementKindModifier.none */, sortText: Completions.SortText.GlobalsOrKeywords }); } return res; }); function getKeywordCompletions(keywordFilter, filterOutTsOnlyKeywords) { if (!filterOutTsOnlyKeywords) return getTypescriptKeywordCompletions(keywordFilter); var index = keywordFilter + 8 /* KeywordCompletionFilters.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 /* KeywordCompletionFilters.None */: return false; case 1 /* KeywordCompletionFilters.All */: return isFunctionLikeBodyKeyword(kind) || kind === 135 /* SyntaxKind.DeclareKeyword */ || kind === 141 /* SyntaxKind.ModuleKeyword */ || kind === 152 /* SyntaxKind.TypeKeyword */ || kind === 142 /* SyntaxKind.NamespaceKeyword */ || kind === 126 /* SyntaxKind.AbstractKeyword */ || ts.isTypeKeyword(kind) && kind !== 153 /* SyntaxKind.UndefinedKeyword */; case 5 /* KeywordCompletionFilters.FunctionLikeBodyKeywords */: return isFunctionLikeBodyKeyword(kind); case 2 /* KeywordCompletionFilters.ClassElementKeywords */: return isClassMemberCompletionKeyword(kind); case 3 /* KeywordCompletionFilters.InterfaceElementKeywords */: return isInterfaceOrTypeLiteralCompletionKeyword(kind); case 4 /* KeywordCompletionFilters.ConstructorParameterKeywords */: return ts.isParameterPropertyModifier(kind); case 6 /* KeywordCompletionFilters.TypeAssertionKeywords */: return ts.isTypeKeyword(kind) || kind === 85 /* SyntaxKind.ConstKeyword */; case 7 /* KeywordCompletionFilters.TypeKeywords */: return ts.isTypeKeyword(kind); case 8 /* KeywordCompletionFilters.TypeKeyword */: return kind === 152 /* SyntaxKind.TypeKeyword */; default: return ts.Debug.assertNever(keywordFilter); } })); } function isTypeScriptOnlyKeyword(kind) { switch (kind) { case 126 /* SyntaxKind.AbstractKeyword */: case 130 /* SyntaxKind.AnyKeyword */: case 158 /* SyntaxKind.BigIntKeyword */: case 133 /* SyntaxKind.BooleanKeyword */: case 135 /* SyntaxKind.DeclareKeyword */: case 92 /* SyntaxKind.EnumKeyword */: case 157 /* SyntaxKind.GlobalKeyword */: case 117 /* SyntaxKind.ImplementsKeyword */: case 137 /* SyntaxKind.InferKeyword */: case 118 /* SyntaxKind.InterfaceKeyword */: case 139 /* SyntaxKind.IsKeyword */: case 140 /* SyntaxKind.KeyOfKeyword */: case 141 /* SyntaxKind.ModuleKeyword */: case 142 /* SyntaxKind.NamespaceKeyword */: case 143 /* SyntaxKind.NeverKeyword */: case 147 /* SyntaxKind.NumberKeyword */: case 148 /* SyntaxKind.ObjectKeyword */: case 159 /* SyntaxKind.OverrideKeyword */: case 121 /* SyntaxKind.PrivateKeyword */: case 122 /* SyntaxKind.ProtectedKeyword */: case 123 /* SyntaxKind.PublicKeyword */: case 145 /* SyntaxKind.ReadonlyKeyword */: case 150 /* SyntaxKind.StringKeyword */: case 151 /* SyntaxKind.SymbolKeyword */: case 152 /* SyntaxKind.TypeKeyword */: case 154 /* SyntaxKind.UniqueKeyword */: case 155 /* SyntaxKind.UnknownKeyword */: return true; default: return false; } } function isInterfaceOrTypeLiteralCompletionKeyword(kind) { return kind === 145 /* SyntaxKind.ReadonlyKeyword */; } function isClassMemberCompletionKeyword(kind) { switch (kind) { case 126 /* SyntaxKind.AbstractKeyword */: case 134 /* SyntaxKind.ConstructorKeyword */: case 136 /* SyntaxKind.GetKeyword */: case 149 /* SyntaxKind.SetKeyword */: case 131 /* SyntaxKind.AsyncKeyword */: case 135 /* SyntaxKind.DeclareKeyword */: case 159 /* SyntaxKind.OverrideKeyword */: return true; default: return ts.isClassMemberModifier(kind); } } function isFunctionLikeBodyKeyword(kind) { return kind === 131 /* SyntaxKind.AsyncKeyword */ || kind === 132 /* SyntaxKind.AwaitKeyword */ || kind === 127 /* SyntaxKind.AsKeyword */ || !ts.isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind); } function keywordForNode(node) { return ts.isIdentifier(node) ? node.originalKeywordKind || 0 /* SyntaxKind.Unknown */ : node.kind; } function getContextualKeywords(contextToken, position) { var entries = []; /** * An `AssertClause` can come after an import declaration: * import * from "foo" | * import "foo" | * or after a re-export declaration that has a module specifier: * export { foo } from "foo" | * Source: https://tc39.es/proposal-import-assertions/ */ if (contextToken) { var file = contextToken.getSourceFile(); var parent = contextToken.parent; var tokenLine = file.getLineAndCharacterOfPosition(contextToken.end).line; var currentLine = file.getLineAndCharacterOfPosition(position).line; if ((ts.isImportDeclaration(parent) || ts.isExportDeclaration(parent) && parent.moduleSpecifier) && contextToken === parent.moduleSpecifier && tokenLine === currentLine) { entries.push({ name: ts.tokenToString(129 /* SyntaxKind.AssertKeyword */), kind: "keyword" /* ScriptElementKind.keyword */, kindModifiers: "" /* ScriptElementKindModifier.none */, sortText: Completions.SortText.GlobalsOrKeywords, }); } } return entries; } /** Get the corresponding JSDocTag node if the position is in a jsDoc comment */ function getJsDocTagAtPosition(node, position) { return ts.findAncestor(node, function (n) { return ts.isJSDocTag(n) && ts.rangeContainsPosition(n, position) ? true : ts.isJSDoc(n) ? "quit" : false; }); } function getPropertiesForObjectExpression(contextualType, completionsType, obj, checker) { var hasCompletionsType = completionsType && completionsType !== contextualType; var type = hasCompletionsType && !(completionsType.flags & 3 /* TypeFlags.AnyOrUnknown */) ? checker.getUnionType([contextualType, completionsType]) : contextualType; var properties = getApparentProperties(type, obj, checker); return type.isClass() && containsNonPublicProperties(properties) ? [] : hasCompletionsType ? ts.filter(properties, 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) { if (!ts.length(member.declarations)) return true; return ts.some(member.declarations, function (decl) { return decl.parent !== obj; }); } } Completions.getPropertiesForObjectExpression = getPropertiesForObjectExpression; function getApparentProperties(type, node, checker) { if (!type.isUnion()) return type.getApparentProperties(); return checker.getAllPossiblePropertiesOfTypes(ts.filter(type.types, function (memberType) { return !(memberType.flags & 131068 /* TypeFlags.Primitive */ || checker.isArrayLikeType(memberType) || checker.isTypeInvalidDueToUnionDiscriminant(memberType, node) || ts.typeHasCallOrConstructSignatures(memberType, checker) || memberType.isClass() && containsNonPublicProperties(memberType.getApparentProperties())); })); } function containsNonPublicProperties(props) { return ts.some(props, function (p) { return !!(ts.getDeclarationModifierFlagsFromSymbol(p) & 24 /* ModifierFlags.NonPublicAccessibilityModifier */); }); } /** * 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 348 /* SyntaxKind.SyntaxList */: return ts.tryCast(location.parent, ts.isObjectTypeDeclaration); case 1 /* SyntaxKind.EndOfFileToken */: var cls = ts.tryCast(ts.lastOrUndefined(ts.cast(location.parent, ts.isSourceFile).statements), ts.isObjectTypeDeclaration); if (cls && !ts.findChildOfKind(cls, 19 /* SyntaxKind.CloseBraceToken */, sourceFile)) { return cls; } break; case 79 /* SyntaxKind.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; // class C { blah; constructor/**/ } and so on if (location.kind === 134 /* SyntaxKind.ConstructorKeyword */ // class C { blah \n constructor/**/ } || (ts.isIdentifier(contextToken) && ts.isPropertyDeclaration(contextToken.parent) && ts.isClassLike(location))) { return ts.findAncestor(contextToken, ts.isClassLike); } switch (contextToken.kind) { case 63 /* SyntaxKind.EqualsToken */: // class c { public prop = | /* global completions */ } return undefined; case 26 /* SyntaxKind.SemicolonToken */: // class c {getValue(): number; | } case 19 /* SyntaxKind.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 /* SyntaxKind.OpenBraceToken */: // class c { | case 27 /* SyntaxKind.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 /* SyntaxKind.AsteriskToken */ || ts.isIdentifier(contextToken) && isValidKeyword(ts.stringToToken(contextToken.text))) // TODO: GH#18217 ? contextToken.parent.parent : undefined; } } function tryGetTypeLiteralNode(node) { if (!node) return undefined; var parent = node.parent; switch (node.kind) { case 18 /* SyntaxKind.OpenBraceToken */: if (ts.isTypeLiteralNode(parent)) { return parent; } break; case 26 /* SyntaxKind.SemicolonToken */: case 27 /* SyntaxKind.CommaToken */: case 79 /* SyntaxKind.Identifier */: if (parent.kind === 166 /* SyntaxKind.PropertySignature */ && ts.isTypeLiteralNode(parent.parent)) { return parent.parent; } break; } return undefined; } function getConstraintOfTypeArgumentProperty(node, checker) { if (!node) return undefined; if (ts.isTypeNode(node) && ts.isTypeReferenceType(node.parent)) { return checker.getTypeArgumentConstraint(node); } var t = getConstraintOfTypeArgumentProperty(node.parent, checker); if (!t) return undefined; switch (node.kind) { case 166 /* SyntaxKind.PropertySignature */: return checker.getTypeOfPropertyOfContextualType(t, node.symbol.escapedName); case 188 /* SyntaxKind.IntersectionType */: case 182 /* SyntaxKind.TypeLiteral */: case 187 /* SyntaxKind.UnionType */: return t; } } // 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 /* SyntaxKind.LessThanToken */ && (!ts.isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent)); case "/": return !!contextToken && (ts.isStringLiteralLike(contextToken) ? !!ts.tryGetImportFromModuleSpecifier(contextToken) : contextToken.kind === 43 /* SyntaxKind.SlashToken */ && ts.isJsxClosingElement(contextToken.parent)); case " ": return !!contextToken && ts.isImportKeyword(contextToken) && contextToken.parent.kind === 305 /* SyntaxKind.SourceFile */; default: return ts.Debug.assertNever(triggerCharacter); } } function binaryExpressionMayBeOpenTag(_a) { var left = _a.left; return ts.nodeIsMissing(left); } /** 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 /* SymbolFlags.Value */, /*excludeGlobals*/ false); if (selfSymbol && checker.getTypeOfSymbolAtLocation(selfSymbol, sourceFile) === type) { return true; } var globalSymbol = checker.resolveName("global", /*location*/ undefined, 111551 /* SymbolFlags.Value */, /*excludeGlobals*/ false); if (globalSymbol && checker.getTypeOfSymbolAtLocation(globalSymbol, sourceFile) === type) { return true; } var globalThisSymbol = checker.resolveName("globalThis", /*location*/ undefined, 111551 /* SymbolFlags.Value */, /*excludeGlobals*/ false); if (globalThisSymbol && checker.getTypeOfSymbolAtLocation(globalThisSymbol, sourceFile) === type) { return true; } return false; } function isStaticProperty(symbol) { return !!(symbol.valueDeclaration && ts.getEffectiveModifierFlags(symbol.valueDeclaration) & 32 /* ModifierFlags.Static */ && ts.isClassLike(symbol.valueDeclaration.parent)); } function tryGetObjectLiteralContextualType(node, typeChecker) { var type = typeChecker.getContextualType(node); if (type) { return type; } var parent = ts.walkUpParenthesizedExpressions(node.parent); if (ts.isBinaryExpression(parent) && parent.operatorToken.kind === 63 /* SyntaxKind.EqualsToken */ && node === parent.left) { // Object literal is assignment pattern: ({ | } = x) return typeChecker.getTypeAtLocation(parent); } if (ts.isExpression(parent)) { // f(() => (({ | }))); return typeChecker.getContextualType(parent); } return undefined; } function getImportStatementCompletionInfo(contextToken) { var keywordCompletion; var isKeywordOnlyCompletion = false; var candidate = getCandidate(); return { isKeywordOnlyCompletion: isKeywordOnlyCompletion, keywordCompletion: keywordCompletion, isNewIdentifierLocation: !!(candidate || keywordCompletion === 152 /* SyntaxKind.TypeKeyword */), replacementNode: candidate && ts.rangeIsOnSingleLine(candidate, candidate.getSourceFile()) ? candidate : undefined }; function getCandidate() { var parent = contextToken.parent; if (ts.isImportEqualsDeclaration(parent)) { keywordCompletion = contextToken.kind === 152 /* SyntaxKind.TypeKeyword */ ? undefined : 152 /* SyntaxKind.TypeKeyword */; return isModuleSpecifierMissingOrEmpty(parent.moduleReference) ? parent : undefined; } if (couldBeTypeOnlyImportSpecifier(parent, contextToken) && canCompleteFromNamedBindings(parent.parent)) { return parent; } if (ts.isNamedImports(parent) || ts.isNamespaceImport(parent)) { if (!parent.parent.isTypeOnly && (contextToken.kind === 18 /* SyntaxKind.OpenBraceToken */ || contextToken.kind === 100 /* SyntaxKind.ImportKeyword */ || contextToken.kind === 27 /* SyntaxKind.CommaToken */)) { keywordCompletion = 152 /* SyntaxKind.TypeKeyword */; } if (canCompleteFromNamedBindings(parent)) { // At `import { ... } |` or `import * as Foo |`, the only possible completion is `from` if (contextToken.kind === 19 /* SyntaxKind.CloseBraceToken */ || contextToken.kind === 79 /* SyntaxKind.Identifier */) { isKeywordOnlyCompletion = true; keywordCompletion = 156 /* SyntaxKind.FromKeyword */; } else { return parent.parent.parent; } } return undefined; } if (ts.isImportKeyword(contextToken) && ts.isSourceFile(parent)) { // A lone import keyword with nothing following it does not parse as a statement at all keywordCompletion = 152 /* SyntaxKind.TypeKeyword */; return contextToken; } if (ts.isImportKeyword(contextToken) && ts.isImportDeclaration(parent)) { // `import s| from` keywordCompletion = 152 /* SyntaxKind.TypeKeyword */; return isModuleSpecifierMissingOrEmpty(parent.moduleSpecifier) ? parent : undefined; } return undefined; } } function couldBeTypeOnlyImportSpecifier(importSpecifier, contextToken) { return ts.isImportSpecifier(importSpecifier) && (importSpecifier.isTypeOnly || contextToken === importSpecifier.name && ts.isTypeKeywordTokenOrIdentifier(contextToken)); } function canCompleteFromNamedBindings(namedBindings) { return isModuleSpecifierMissingOrEmpty(namedBindings.parent.parent.moduleSpecifier) && (ts.isNamespaceImport(namedBindings) || namedBindings.elements.length < 2) && !namedBindings.parent.name; } function isModuleSpecifierMissingOrEmpty(specifier) { var _a; if (ts.nodeIsMissing(specifier)) return true; return !((_a = ts.tryCast(ts.isExternalModuleReference(specifier) ? specifier.expression : specifier, ts.isStringLiteralLike)) === null || _a === void 0 ? void 0 : _a.text); } function getVariableDeclaration(property) { var variableDeclaration = ts.findAncestor(property, function (node) { return ts.isFunctionBlock(node) || isArrowFunctionBody(node) || ts.isBindingPattern(node) ? "quit" : ts.isVariableDeclaration(node); }); return variableDeclaration; } function isArrowFunctionBody(node) { return node.parent && ts.isArrowFunction(node.parent) && node.parent.body === node; } ; /** True if symbol is a type or a module containing at least one type. */ function symbolCanBeReferencedAtTypeLocation(symbol, checker, seenModules) { if (seenModules === void 0) { seenModules = new ts.Map(); } // Since an alias can be merged with a local declaration, we need to test both the alias and its target. // This code used to just test the result of `skipAlias`, but that would ignore any locally introduced meanings. return nonAliasCanBeReferencedAtTypeLocation(symbol) || nonAliasCanBeReferencedAtTypeLocation(ts.skipAlias(symbol.exportSymbol || symbol, checker)); function nonAliasCanBeReferencedAtTypeLocation(symbol) { return !!(symbol.flags & 788968 /* SymbolFlags.Type */) || checker.isUnknownSymbol(symbol) || !!(symbol.flags & 1536 /* SymbolFlags.Module */) && ts.addToSeen(seenModules, ts.getSymbolId(symbol)) && checker.getExportsOfModule(symbol).some(function (e) { return symbolCanBeReferencedAtTypeLocation(e, checker, seenModules); }); } } function isDeprecated(symbol, checker) { var declarations = ts.skipAlias(symbol, checker).declarations; return !!ts.length(declarations) && ts.every(declarations, ts.isDeprecatedDeclaration); } /** * True if the first character of `lowercaseCharacters` is the first character * of some "word" in `identiferString` (where the string is split into "words" * by camelCase and snake_case segments), then if the remaining characters of * `lowercaseCharacters` appear, in order, in the rest of `identifierString`. * * True: * 'state' in 'useState' * 'sae' in 'useState' * 'viable' in 'ENVIRONMENT_VARIABLE' * * False: * 'staet' in 'useState' * 'tate' in 'useState' * 'ment' in 'ENVIRONMENT_VARIABLE' */ function charactersFuzzyMatchInString(identifierString, lowercaseCharacters) { if (lowercaseCharacters.length === 0) { return true; } var matchedFirstCharacter = false; var prevChar; var characterIndex = 0; var len = identifierString.length; for (var strIndex = 0; strIndex < len; strIndex++) { var strChar = identifierString.charCodeAt(strIndex); var testChar = lowercaseCharacters.charCodeAt(characterIndex); if (strChar === testChar || strChar === toUpperCharCode(testChar)) { matchedFirstCharacter || (matchedFirstCharacter = prevChar === undefined || // Beginning of word 97 /* CharacterCodes.a */ <= prevChar && prevChar <= 122 /* CharacterCodes.z */ && 65 /* CharacterCodes.A */ <= strChar && strChar <= 90 /* CharacterCodes.Z */ || // camelCase transition prevChar === 95 /* CharacterCodes._ */ && strChar !== 95 /* CharacterCodes._ */); // snake_case transition if (matchedFirstCharacter) { characterIndex++; } if (characterIndex === lowercaseCharacters.length) { return true; } } prevChar = strChar; } // Did not find all characters return false; } function toUpperCharCode(charCode) { if (97 /* CharacterCodes.a */ <= charCode && charCode <= 122 /* CharacterCodes.z */) { return charCode - 32; } return charCode; } })(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" /* HighlightSpanKind.none */ }; } function getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) { var sourceFilesSet = new ts.Set(sourceFilesToSearch.map(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; }); var getCanonicalFileName = ts.createGetCanonicalFileName(program.useCaseSensitiveFileNames()); return ts.mapDefined(ts.arrayFrom(map.entries()), function (_a) { var fileName = _a[0], highlightSpans = _a[1]; if (!sourceFilesSet.has(fileName)) { if (!program.redirectTargetsMap.has(ts.toPath(fileName, program.getCurrentDirectory(), getCanonicalFileName))) { return undefined; } 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 99 /* SyntaxKind.IfKeyword */: case 91 /* SyntaxKind.ElseKeyword */: return ts.isIfStatement(node.parent) ? getIfElseOccurrences(node.parent, sourceFile) : undefined; case 105 /* SyntaxKind.ReturnKeyword */: return useParent(node.parent, ts.isReturnStatement, getReturnOccurrences); case 109 /* SyntaxKind.ThrowKeyword */: return useParent(node.parent, ts.isThrowStatement, getThrowOccurrences); case 111 /* SyntaxKind.TryKeyword */: case 83 /* SyntaxKind.CatchKeyword */: case 96 /* SyntaxKind.FinallyKeyword */: var tryStatement = node.kind === 83 /* SyntaxKind.CatchKeyword */ ? node.parent.parent : node.parent; return useParent(tryStatement, ts.isTryStatement, getTryCatchFinallyOccurrences); case 107 /* SyntaxKind.SwitchKeyword */: return useParent(node.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences); case 82 /* SyntaxKind.CaseKeyword */: case 88 /* SyntaxKind.DefaultKeyword */: { if (ts.isDefaultClause(node.parent) || ts.isCaseClause(node.parent)) { return useParent(node.parent.parent.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences); } return undefined; } case 81 /* SyntaxKind.BreakKeyword */: case 86 /* SyntaxKind.ContinueKeyword */: return useParent(node.parent, ts.isBreakOrContinueStatement, getBreakOrContinueStatementOccurrences); case 97 /* SyntaxKind.ForKeyword */: case 115 /* SyntaxKind.WhileKeyword */: case 90 /* SyntaxKind.DoKeyword */: return useParent(node.parent, function (n) { return ts.isIterationStatement(n, /*lookInLabeledStatements*/ true); }, getLoopBreakContinueOccurrences); case 134 /* SyntaxKind.ConstructorKeyword */: return getFromAllDeclarations(ts.isConstructorDeclaration, [134 /* SyntaxKind.ConstructorKeyword */]); case 136 /* SyntaxKind.GetKeyword */: case 149 /* SyntaxKind.SetKeyword */: return getFromAllDeclarations(ts.isAccessor, [136 /* SyntaxKind.GetKeyword */, 149 /* SyntaxKind.SetKeyword */]); case 132 /* SyntaxKind.AwaitKeyword */: return useParent(node.parent, ts.isAwaitExpression, getAsyncAndAwaitOccurrences); case 131 /* SyntaxKind.AsyncKeyword */: return highlightSpans(getAsyncAndAwaitOccurrences(node)); case 125 /* SyntaxKind.YieldKeyword */: return highlightSpans(getYieldOccurrences(node)); case 101 /* SyntaxKind.InKeyword */: return undefined; 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 === 305 /* SyntaxKind.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 249 /* SyntaxKind.SwitchStatement */: if (statement.kind === 245 /* SyntaxKind.ContinueStatement */) { return false; } // falls through case 242 /* SyntaxKind.ForStatement */: case 243 /* SyntaxKind.ForInStatement */: case 244 /* SyntaxKind.ForOfStatement */: case 241 /* SyntaxKind.WhileStatement */: case 240 /* SyntaxKind.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 262 /* SyntaxKind.ModuleBlock */: case 305 /* SyntaxKind.SourceFile */: case 235 /* SyntaxKind.Block */: case 289 /* SyntaxKind.CaseClause */: case 290 /* SyntaxKind.DefaultClause */: // Container is either a class declaration or the declaration is a classDeclaration if (modifierFlag & 128 /* ModifierFlags.Abstract */ && ts.isClassDeclaration(declaration)) { return __spreadArray(__spreadArray([], declaration.members, true), [declaration], false); } else { return container.statements; } case 171 /* SyntaxKind.Constructor */: case 169 /* SyntaxKind.MethodDeclaration */: case 256 /* SyntaxKind.FunctionDeclaration */: return __spreadArray(__spreadArray([], container.parameters, true), (ts.isClassLike(container.parent) ? container.parent.members : []), true); case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 182 /* SyntaxKind.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 /* ModifierFlags.AccessibilityModifier */ | 64 /* ModifierFlags.Readonly */)) { var constructor = ts.find(container.members, ts.isConstructorDeclaration); if (constructor) { return __spreadArray(__spreadArray([], nodes, true), constructor.parameters, true); } } else if (modifierFlag & 128 /* ModifierFlags.Abstract */) { return __spreadArray(__spreadArray([], nodes, true), [container], false); } return nodes; // Syntactically invalid positions that the parser might produce anyway case 205 /* SyntaxKind.ObjectLiteralExpression */: return undefined; 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(), 97 /* SyntaxKind.ForKeyword */, 115 /* SyntaxKind.WhileKeyword */, 90 /* SyntaxKind.DoKeyword */)) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. if (loopNode.kind === 240 /* SyntaxKind.DoStatement */) { var loopTokens = loopNode.getChildren(); for (var i = loopTokens.length - 1; i >= 0; i--) { if (pushKeywordIf(keywords, loopTokens[i], 115 /* SyntaxKind.WhileKeyword */)) { break; } } } } ts.forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), function (statement) { if (ownsBreakOrContinueStatement(loopNode, statement)) { pushKeywordIf(keywords, statement.getFirstToken(), 81 /* SyntaxKind.BreakKeyword */, 86 /* SyntaxKind.ContinueKeyword */); } }); return keywords; } function getBreakOrContinueStatementOccurrences(breakOrContinueStatement) { var owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { case 242 /* SyntaxKind.ForStatement */: case 243 /* SyntaxKind.ForInStatement */: case 244 /* SyntaxKind.ForOfStatement */: case 240 /* SyntaxKind.DoStatement */: case 241 /* SyntaxKind.WhileStatement */: return getLoopBreakContinueOccurrences(owner); case 249 /* SyntaxKind.SwitchStatement */: return getSwitchCaseDefaultOccurrences(owner); } } return undefined; } function getSwitchCaseDefaultOccurrences(switchStatement) { var keywords = []; pushKeywordIf(keywords, switchStatement.getFirstToken(), 107 /* SyntaxKind.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(), 82 /* SyntaxKind.CaseKeyword */, 88 /* SyntaxKind.DefaultKeyword */); ts.forEach(aggregateAllBreakAndContinueStatements(clause), function (statement) { if (ownsBreakOrContinueStatement(switchStatement, statement)) { pushKeywordIf(keywords, statement.getFirstToken(), 81 /* SyntaxKind.BreakKeyword */); } }); }); return keywords; } function getTryCatchFinallyOccurrences(tryStatement, sourceFile) { var keywords = []; pushKeywordIf(keywords, tryStatement.getFirstToken(), 111 /* SyntaxKind.TryKeyword */); if (tryStatement.catchClause) { pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 83 /* SyntaxKind.CatchKeyword */); } if (tryStatement.finallyBlock) { var finallyKeyword = ts.findChildOfKind(tryStatement, 96 /* SyntaxKind.FinallyKeyword */, sourceFile); pushKeywordIf(keywords, finallyKeyword, 96 /* SyntaxKind.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, 109 /* SyntaxKind.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, 105 /* SyntaxKind.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, 105 /* SyntaxKind.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, 109 /* SyntaxKind.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, 131 /* SyntaxKind.AsyncKeyword */); }); } ts.forEachChild(func, function (child) { traverseWithoutCrossingFunction(child, function (node) { if (ts.isAwaitExpression(node)) { pushKeywordIf(keywords, node.getFirstToken(), 132 /* SyntaxKind.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(), 125 /* SyntaxKind.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 === 91 /* SyntaxKind.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" /* HighlightSpanKind.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], 99 /* SyntaxKind.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], 91 /* SyntaxKind.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 isDocumentRegistryEntry(entry) { return !!entry.sourceFile; } 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 = new ts.Map(); 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) { if (isDocumentRegistryEntry(entry)) { sourceFiles.push({ name: name, scriptKind: entry.sourceFile.scriptKind, refCount: entry.languageServiceRefCount }); } else { entry.forEach(function (value, scriptKind) { return sourceFiles.push({ name: name, scriptKind: scriptKind, refCount: value.languageServiceRefCount }); }); } }); sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; }); return { bucket: name, sourceFiles: sourceFiles }; }); return JSON.stringify(bucketInfoArray, undefined, 2); } function getCompilationSettings(settingsOrHost) { if (typeof settingsOrHost.getCompilationSettings === "function") { return settingsOrHost.getCompilationSettings(); } return settingsOrHost; } function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var key = getKeyForCompilationSettings(getCompilationSettings(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(getCompilationSettings(compilationSettings)); return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind); } function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) { return acquireOrUpdateDocument(fileName, path, getCompilationSettings(compilationSettings), key, scriptSnapshot, version, /*acquiring*/ false, scriptKind); } function getDocumentRegistryEntry(bucketEntry, scriptKind) { var entry = isDocumentRegistryEntry(bucketEntry) ? bucketEntry : bucketEntry.get(ts.Debug.checkDefined(scriptKind, "If there are more than one scriptKind's for same document the scriptKind should be provided")); ts.Debug.assert(scriptKind === undefined || !entry || entry.sourceFile.scriptKind === scriptKind, "Script kind should match provided ScriptKind:".concat(scriptKind, " and sourceFile.scriptKind: ").concat(entry === null || entry === void 0 ? void 0 : entry.sourceFile.scriptKind, ", !entry: ").concat(!entry)); return entry; } function acquireOrUpdateDocument(fileName, path, compilationSettingsOrHost, key, scriptSnapshot, version, acquiring, scriptKind) { var _a, _b, _c, _d; scriptKind = ts.ensureScriptKind(fileName, scriptKind); var compilationSettings = getCompilationSettings(compilationSettingsOrHost); var host = compilationSettingsOrHost === compilationSettings ? undefined : compilationSettingsOrHost; var scriptTarget = scriptKind === 6 /* ScriptKind.JSON */ ? 100 /* ScriptTarget.JSON */ : ts.getEmitScriptTarget(compilationSettings); var sourceFileOptions = { languageVersion: scriptTarget, impliedNodeFormat: host && ts.getImpliedNodeFormatForFile(path, (_d = (_c = (_b = (_a = host.getCompilerHost) === null || _a === void 0 ? void 0 : _a.call(host)) === null || _b === void 0 ? void 0 : _b.getModuleResolutionCache) === null || _c === void 0 ? void 0 : _c.call(_b)) === null || _d === void 0 ? void 0 : _d.getPackageJsonInfoCache(), host, compilationSettings), setExternalModuleIndicator: ts.getSetExternalModuleIndicator(compilationSettings) }; var oldBucketCount = buckets.size; var bucket = ts.getOrUpdate(buckets, key, function () { return new ts.Map(); }); if (ts.tracing) { if (buckets.size > oldBucketCount) { // It is interesting, but not definitively problematic if a build requires multiple document registry buckets - // perhaps they are for two projects that don't have any overlap. // Bonus: these events can help us interpret the more interesting event below. ts.tracing.instant("session" /* tracing.Phase.Session */, "createdDocumentRegistryBucket", { configFilePath: compilationSettings.configFilePath, key: key }); } // It is fairly suspicious to have one path in two buckets - you'd expect dependencies to have similar configurations. // If this occurs unexpectedly, the fix is likely to synchronize the project settings. // Skip .d.ts files to reduce noise (should also cover most of node_modules). var otherBucketKey = !ts.isDeclarationFileName(path) && ts.forEachEntry(buckets, function (bucket, bucketKey) { return bucketKey !== key && bucket.has(path) && bucketKey; }); if (otherBucketKey) { ts.tracing.instant("session" /* tracing.Phase.Session */, "documentRegistryBucketOverlap", { path: path, key1: otherBucketKey, key2: key }); } } var bucketEntry = bucket.get(path); var entry = bucketEntry && getDocumentRegistryEntry(bucketEntry, scriptKind); if (!entry && externalCache) { var sourceFile = externalCache.getDocument(key, path); if (sourceFile) { ts.Debug.assert(acquiring); entry = { sourceFile: sourceFile, languageServiceRefCount: 0 }; setBucketEntry(); } } if (!entry) { // Have never seen this file with these settings. Create a new source file for it. var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, sourceFileOptions, version, /*setNodeParents*/ false, scriptKind); if (externalCache) { externalCache.setDocument(key, path, sourceFile); } entry = { sourceFile: sourceFile, languageServiceRefCount: 1, }; setBucketEntry(); } 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 setBucketEntry() { if (!bucketEntry) { bucket.set(path, entry); } else if (isDocumentRegistryEntry(bucketEntry)) { var scriptKindMap = new ts.Map(); scriptKindMap.set(bucketEntry.sourceFile.scriptKind, bucketEntry); scriptKindMap.set(scriptKind, entry); bucket.set(path, scriptKindMap); } else { bucketEntry.set(scriptKind, entry); } } } function releaseDocument(fileName, compilationSettings, scriptKind) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var key = getKeyForCompilationSettings(compilationSettings); return releaseDocumentWithKey(path, key, scriptKind); } function releaseDocumentWithKey(path, key, scriptKind) { var bucket = ts.Debug.checkDefined(buckets.get(key)); var bucketEntry = bucket.get(path); var entry = getDocumentRegistryEntry(bucketEntry, scriptKind); entry.languageServiceRefCount--; ts.Debug.assert(entry.languageServiceRefCount >= 0); if (entry.languageServiceRefCount === 0) { if (isDocumentRegistryEntry(bucketEntry)) { bucket.delete(path); } else { bucketEntry.delete(scriptKind); if (bucketEntry.size === 1) { bucket.set(path, ts.firstDefinedIterator(bucketEntry.values(), ts.identity)); } } } } function getLanguageServiceRefCounts(path, scriptKind) { return ts.arrayFrom(buckets.entries(), function (_a) { var key = _a[0], bucket = _a[1]; var bucketEntry = bucket.get(path); var entry = bucketEntry && getDocumentRegistryEntry(bucketEntry, scriptKind); 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 compilerOptionValueToString(value) { var _a; if (value === null || typeof value !== "object") { // eslint-disable-line no-null/no-null return "" + value; } if (ts.isArray(value)) { return "[".concat((_a = ts.map(value, function (e) { return compilerOptionValueToString(e); })) === null || _a === void 0 ? void 0 : _a.join(","), "]"); } var str = "{"; for (var key in value) { if (ts.hasOwnProperty.call(value, key)) { // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier str += "".concat(key, ": ").concat(compilerOptionValueToString(value[key])); } } return str + "}"; } function getKeyForCompilationSettings(settings) { return ts.sourceFileAffectingCompilerOptions.map(function (option) { return compilerOptionValueToString(ts.getCompilerOptionValue(settings, option)); }).join("|") + (settings.pathsBasePath ? "|".concat(settings.pathsBasePath) : undefined); } })(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. if (exportingModuleSymbol.declarations) { 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 208 /* SyntaxKind.CallExpression */: if (ts.isImportCall(direct)) { handleImportCall(direct); break; } if (!isAvailableThroughGlobal) { var parent = direct.parent; if (exportKind === 2 /* ExportKind.ExportEquals */ && parent.kind === 254 /* SyntaxKind.VariableDeclaration */) { var name = parent.name; if (name.kind === 79 /* SyntaxKind.Identifier */) { directImports.push(name); break; } } } break; case 79 /* SyntaxKind.Identifier */: // for 'const x = require("y"); break; // TODO: GH#23879 case 265 /* SyntaxKind.ImportEqualsDeclaration */: handleNamespaceImport(direct, direct.name, ts.hasSyntacticModifier(direct, 1 /* ModifierFlags.Export */), /*alreadyAddedDirect*/ false); break; case 266 /* SyntaxKind.ImportDeclaration */: directImports.push(direct); var namedBindings = direct.importClause && direct.importClause.namedBindings; if (namedBindings && namedBindings.kind === 268 /* SyntaxKind.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 272 /* SyntaxKind.ExportDeclaration */: if (!direct.exportClause) { // This is `export * from "foo"`, so imports of this module may import the export too. handleDirectImports(getContainingModuleSymbol(direct, checker)); } else if (direct.exportClause.kind === 274 /* SyntaxKind.NamespaceExport */) { // `export * as foo from "foo"` add to indirect uses addIndirectUser(getSourceFileLikeForImportDeclaration(direct), /** addTransitiveDependencies */ true); } 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 200 /* SyntaxKind.ImportType */: // Only check for typeof import('xyz') if (direct.isTypeOf && !direct.qualifier && isExported(direct)) { addIndirectUser(direct.getSourceFile(), /** addTransitiveDependencies */ true); } directImports.push(direct); break; default: ts.Debug.failBadSyntaxKind(direct, "Unexpected import kind."); } } } } function handleImportCall(importCall) { var top = ts.findAncestor(importCall, isAmbientModuleDeclaration) || importCall.getSourceFile(); addIndirectUser(top, /** addTransitiveDependencies */ !!isExported(importCall, /** stopAtAmbientModule */ true)); } function isExported(node, stopAtAmbientModule) { if (stopAtAmbientModule === void 0) { stopAtAmbientModule = false; } return ts.findAncestor(node, function (node) { if (stopAtAmbientModule && isAmbientModuleDeclaration(node)) return "quit"; return ts.some(node.modifiers, function (mod) { return mod.kind === 93 /* SyntaxKind.ExportKeyword */; }); }); } function handleNamespaceImport(importDeclaration, name, isReExport, alreadyAddedDirect) { if (exportKind === 2 /* ExportKind.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 === 305 /* SyntaxKind.SourceFile */ || sourceFileLike.kind === 261 /* SyntaxKind.ModuleDeclaration */); if (isReExport || findNamespaceReExports(sourceFileLike, name, checker)) { addIndirectUser(sourceFileLike, /** addTransitiveDependencies */ true); } else { addIndirectUser(sourceFileLike); } } } /** Adds a module and all of its transitive dependencies as possible indirect users. */ function addIndirectUser(sourceFileLike, addTransitiveDependencies) { if (addTransitiveDependencies === void 0) { addTransitiveDependencies = false; } ts.Debug.assert(!isAvailableThroughGlobal); var isNew = markSeenIndirectUser(sourceFileLike); if (!isNew) return; indirectUserDeclarations.push(sourceFileLike); // TODO: GH#18217 if (!addTransitiveDependencies) return; var moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol); if (!moduleSymbol) return; ts.Debug.assert(!!(moduleSymbol.flags & 1536 /* SymbolFlags.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)) { addIndirectUser(getSourceFileLikeForImportDeclaration(directImport), /** addTransitiveDependencies */ true); } } } } 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 === 265 /* SyntaxKind.ImportEqualsDeclaration */) { if (isExternalModuleImportEquals(decl)) { handleNamespaceImportLike(decl.name); } return; } if (decl.kind === 79 /* SyntaxKind.Identifier */) { handleNamespaceImportLike(decl); return; } if (decl.kind === 200 /* SyntaxKind.ImportType */) { if (decl.qualifier) { var firstIdentifier = ts.getFirstIdentifier(decl.qualifier); if (firstIdentifier.escapedText === ts.symbolName(exportSymbol)) { singleReferences.push(firstIdentifier); } } else if (exportKind === 2 /* ExportKind.ExportEquals */) { singleReferences.push(decl.argument.literal); } return; } // Ignore if there's a grammar error if (decl.moduleSpecifier.kind !== 10 /* SyntaxKind.StringLiteral */) { return; } if (decl.kind === 272 /* SyntaxKind.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 268 /* SyntaxKind.NamespaceImport */: handleNamespaceImportLike(namedBindings.name); break; case 269 /* SyntaxKind.NamedImports */: // 'default' might be accessed as a named import `{ default as foo }`. if (exportKind === 0 /* ExportKind.Named */ || exportKind === 1 /* ExportKind.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 /* ExportKind.Default */ || exportKind === 2 /* ExportKind.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 /* ExportKind.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 === 275 /* SyntaxKind.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 /* ExportKind.Named */ && name === "default" /* InternalSymbolName.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 === null || searchSourceFile === void 0 ? void 0 : searchSourceFile.kind) === 305 /* SyntaxKind.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, ref.resolutionMode || referencingFile.impliedNodeFormat); 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 = new ts.Map(); 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 === 305 /* SyntaxKind.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 272 /* SyntaxKind.ExportDeclaration */: case 266 /* SyntaxKind.ImportDeclaration */: { var decl = statement; if (decl.moduleSpecifier && ts.isStringLiteral(decl.moduleSpecifier)) { action(decl, decl.moduleSpecifier); } break; } case 265 /* SyntaxKind.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 _a; var parent = node.parent; var grandparent = parent.parent; if (symbol.exportSymbol) { if (parent.kind === 206 /* SyntaxKind.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 ((_a = symbol.declarations) === null || _a === void 0 ? void 0 : _a.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.hasSyntacticModifier(exportNode, 1 /* ModifierFlags.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 /* ImportExport.Import */, symbol: lhsSymbol }; } else { return exportInfo(symbol, getExportKindForDeclaration(exportNode)); } } else if (ts.isNamespaceExport(parent)) { return exportInfo(symbol, 0 /* ExportKind.Named */); } // 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 /* ExportKind.Named */); } } function getExportAssignmentExport(ex) { // Get the symbol for the `export =` node; its parent is the module it's the export of. if (!ex.symbol.parent) return undefined; var exportKind = ex.isExportEquals ? 2 /* ExportKind.ExportEquals */ : 1 /* ExportKind.Default */; return { kind: 1 /* ImportExport.Export */, symbol: symbol, exportInfo: { exportingModuleSymbol: ex.symbol.parent, exportKind: exportKind } }; } function getSpecialPropertyExport(node, useLhsSymbol) { var kind; switch (ts.getAssignmentDeclarationKind(node)) { case 1 /* AssignmentDeclarationKind.ExportsProperty */: kind = 0 /* ExportKind.Named */; break; case 2 /* AssignmentDeclarationKind.ModuleExports */: kind = 2 /* ExportKind.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" /* InternalSymbolName.Default */ || importedName === symbol.escapedName) { return { kind: 0 /* ImportExport.Import */, symbol: importedSymbol }; } } function exportInfo(symbol, kind) { var exportInfo = getExportInfo(symbol, kind, checker); return exportInfo && { kind: 1 /* ImportExport.Export */, symbol: symbol, exportInfo: exportInfo }; } // Not meant for use with export specifiers or export assignment. function getExportKindForDeclaration(node) { return ts.hasSyntacticModifier(node, 512 /* ModifierFlags.Default */) ? 1 /* ExportKind.Default */ : 0 /* ExportKind.Named */; } } FindAllReferences.getImportOrExportSymbol = getImportOrExportSymbol; function getExportEqualsLocalSymbol(importedSymbol, checker) { if (importedSymbol.flags & 2097152 /* SymbolFlags.Alias */) { return ts.Debug.checkDefined(checker.getImmediateAliasedSymbol(importedSymbol)); } var decl = ts.Debug.checkDefined(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 265 /* SyntaxKind.ImportEqualsDeclaration */: return parent.name === node && isExternalModuleImportEquals(parent); case 270 /* SyntaxKind.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 267 /* SyntaxKind.ImportClause */: case 268 /* SyntaxKind.NamespaceImport */: ts.Debug.assert(parent.name === node); return true; case 203 /* SyntaxKind.BindingElement */: return ts.isInJSFile(node) && ts.isVariableDeclarationInitializedToBareOrAccessedRequire(parent.parent.parent); 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); } else if (ts.isPropertyAccessExpression(declaration) && ts.isModuleExportsAccessExpression(declaration.expression) && !ts.isPrivateIdentifier(declaration.name)) { // Export of form 'module.exports.propName = expr'; return checker.getSymbolAtLocation(declaration); } else if (ts.isShorthandPropertyAssignment(declaration) && ts.isBinaryExpression(declaration.parent.parent) && ts.getAssignmentDeclarationKind(declaration.parent.parent) === 2 /* AssignmentDeclarationKind.ModuleExports */) { return checker.getExportSpecifierLocalTargetSymbol(declaration.name); } } } return symbol; } function getContainingModuleSymbol(importer, checker) { return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol); } function getSourceFileLikeForImportDeclaration(node) { if (node.kind === 208 /* SyntaxKind.CallExpression */) { return node.getSourceFile(); } var parent = node.parent; if (parent.kind === 305 /* SyntaxKind.SourceFile */) { return parent; } ts.Debug.assert(parent.kind === 262 /* SyntaxKind.ModuleBlock */); return ts.cast(parent.parent, isAmbientModuleDeclaration); } function isAmbientModuleDeclaration(node) { return node.kind === 261 /* SyntaxKind.ModuleDeclaration */ && node.name.kind === 10 /* SyntaxKind.StringLiteral */; } function isExternalModuleImportEquals(eq) { return eq.moduleReference.kind === 277 /* SyntaxKind.ExternalModuleReference */ && eq.moduleReference.expression.kind === 10 /* SyntaxKind.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[DefinitionKind["TripleSlashReference"] = 5] = "TripleSlashReference"; })(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 /* EntryKind.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 /* AssignmentDeclarationKind.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 === 88 /* SyntaxKind.DefaultKeyword */ && ts.hasSyntacticModifier(node.parent, 513 /* ModifierFlags.ExportDefault */))) { return getContextNode(node.parent); } return undefined; } function getContextNode(node) { if (!node) return undefined; switch (node.kind) { case 254 /* SyntaxKind.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 203 /* SyntaxKind.BindingElement */: return getContextNode(node.parent.parent); case 270 /* SyntaxKind.ImportSpecifier */: return node.parent.parent.parent; case 275 /* SyntaxKind.ExportSpecifier */: case 268 /* SyntaxKind.NamespaceImport */: return node.parent.parent; case 267 /* SyntaxKind.ImportClause */: case 274 /* SyntaxKind.NamespaceExport */: return node.parent; case 221 /* SyntaxKind.BinaryExpression */: return ts.isExpressionStatement(node.parent) ? node.parent : node; case 244 /* SyntaxKind.ForOfStatement */: case 243 /* SyntaxKind.ForInStatement */: return { start: node.initializer, end: node.expression }; case 296 /* SyntaxKind.PropertyAssignment */: case 297 /* SyntaxKind.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 options = { use: 1 /* FindReferencesUse.References */ }; var referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options); var checker = program.getTypeChecker(); // Unless the starting node is a declaration (vs e.g. JSDoc), don't attempt to compute isDefinition var adjustedNode = Core.getAdjustedNode(node, options); var symbol = isDefinitionForReference(adjustedNode) ? checker.getSymbolAtLocation(adjustedNode) : undefined; 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(function (r) { return toReferencedSymbolEntry(r, symbol); }) }; }); } FindAllReferences.findReferencedSymbols = findReferencedSymbols; function isDefinitionForReference(node) { return node.kind === 88 /* SyntaxKind.DefaultKeyword */ || !!ts.getDeclarationFromName(node) || ts.isLiteralComputedPropertyDeclarationName(node) || (node.kind === 134 /* SyntaxKind.ConstructorKeyword */ && ts.isConstructorDeclaration(node.parent)); } 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 === 206 /* SyntaxKind.PropertyAccessExpression */ || node.parent.kind === 203 /* SyntaxKind.BindingElement */ || node.parent.kind === 207 /* SyntaxKind.ElementAccessExpression */ || node.kind === 106 /* SyntaxKind.SuperKeyword */) { referenceEntries = entries && __spreadArray([], entries, true); } else { var queue = entries && __spreadArray([], entries, true); var seenNodes = new ts.Map(); 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 === 305 /* SyntaxKind.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 === 297 /* SyntaxKind.ShorthandPropertyAssignment */) { var result_2 = []; Core.getReferenceEntriesForShorthandPropertyAssignment(node, checker, function (node) { return result_2.push(nodeEntry(node)); }); return result_2; } else if (node.kind === 106 /* SyntaxKind.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 /* FindReferencesUse.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 = new ts.Set(sourceFiles.map(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 /* DefinitionKind.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.firstOrUndefined(symbol.declarations); var node = declaration ? (ts.getNameOfDeclaration(declaration) || declaration) : originalNode; return __assign(__assign({}, getFileAndTextSpanFromNode(node)), { name: name_1, kind: kind_1, displayParts: displayParts_1, context: getContextNode(declaration) }); } case 1 /* DefinitionKind.Label */: { var node = def.node; return __assign(__assign({}, getFileAndTextSpanFromNode(node)), { name: node.text, kind: "label" /* ScriptElementKind.label */, displayParts: [ts.displayPart(node.text, ts.SymbolDisplayPartKind.text)] }); } case 2 /* DefinitionKind.Keyword */: { var node = def.node; var name_2 = ts.tokenToString(node.kind); return __assign(__assign({}, getFileAndTextSpanFromNode(node)), { name: name_2, kind: "keyword" /* ScriptElementKind.keyword */, displayParts: [{ text: name_2, kind: "keyword" /* ScriptElementKind.keyword */ }] }); } case 3 /* DefinitionKind.This */: { var node = def.node; var symbol = checker.getSymbolAtLocation(node); var displayParts_2 = symbol && ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, node.getSourceFile(), ts.getContainerNode(node), node).displayParts || [ts.textPart("this")]; return __assign(__assign({}, getFileAndTextSpanFromNode(node)), { name: "this", kind: "var" /* ScriptElementKind.variableElement */, displayParts: displayParts_2 }); } case 4 /* DefinitionKind.String */: { var node = def.node; return __assign(__assign({}, getFileAndTextSpanFromNode(node)), { name: node.text, kind: "var" /* ScriptElementKind.variableElement */, displayParts: [ts.displayPart(ts.getTextOfNode(node), ts.SymbolDisplayPartKind.stringLiteral)] }); } case 5 /* DefinitionKind.TripleSlashReference */: { return { textSpan: ts.createTextSpanFromRange(def.reference), sourceFile: def.file, name: def.reference.fileName, kind: "string" /* ScriptElementKind.string */, displayParts: [ts.displayPart("\"".concat(def.reference.fileName, "\""), ts.SymbolDisplayPartKind.stringLiteral)] }; } default: return ts.Debug.assertNever(def); } })(); var sourceFile = info.sourceFile, textSpan = info.textSpan, name = info.name, kind = info.kind, displayParts = info.displayParts, context = info.context; return __assign({ containerKind: "" /* ScriptElementKind.unknown */, containerName: "", fileName: sourceFile.fileName, kind: kind, name: name, textSpan: textSpan, displayParts: displayParts }, toContextSpan(textSpan, sourceFile, context)); } function getFileAndTextSpanFromNode(node) { var sourceFile = node.getSourceFile(); return { sourceFile: sourceFile, textSpan: getTextSpan(ts.isComputedPropertyName(node) ? node.expression : node, sourceFile) }; } 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 toReferencedSymbolEntry(entry, symbol) { var referenceEntry = toReferenceEntry(entry); if (!symbol) return referenceEntry; return __assign(__assign({}, referenceEntry), { isDefinition: entry.kind !== 0 /* EntryKind.Span */ && isDeclarationOfSymbol(entry.node, symbol) }); } function toReferenceEntry(entry) { var documentSpan = entryToDocumentSpan(entry); if (entry.kind === 0 /* EntryKind.Span */) { return __assign(__assign({}, documentSpan), { isWriteAccess: false }); } var kind = entry.kind, node = entry.node; return __assign(__assign({}, documentSpan), { isWriteAccess: isWriteAccessForReference(node), isInString: kind === 2 /* EntryKind.StringLiteral */ ? true : undefined }); } FindAllReferences.toReferenceEntry = toReferenceEntry; function entryToDocumentSpan(entry) { if (entry.kind === 0 /* EntryKind.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 /* EntryKind.Span */ && ts.isIdentifier(originalNode)) { var node = entry.node, kind = entry.kind; var parent = node.parent; var name = originalNode.text; var isShorthandAssignment = ts.isShorthandPropertyAssignment(parent); if (isShorthandAssignment || (ts.isObjectBindingElementWithoutPropertyName(parent) && parent.name === node && parent.dotDotDotToken === undefined)) { var prefixColon = { prefixText: name + ": " }; var suffixColon = { suffixText: ": " + name }; if (kind === 3 /* EntryKind.SearchedLocalFoundProperty */) { return prefixColon; } if (kind === 4 /* EntryKind.SearchedPropertyFoundLocal */) { return 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. if (isShorthandAssignment) { var grandParent = parent.parent; if (ts.isObjectLiteralExpression(grandParent) && ts.isBinaryExpression(grandParent.parent) && ts.isModuleExportsAccessExpression(grandParent.parent.left)) { return prefixColon; } return suffixColon; } else { return prefixColon; } } else if (ts.isImportSpecifier(parent) && !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, parent) ? { prefixText: name + " as " } : ts.emptyOptions; } else if (ts.isExportSpecifier(parent) && !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 /* EntryKind.Span */) { var node = entry.node; return __assign(__assign({}, documentSpan), implementationKindDisplayParts(node, checker)); } else { return __assign(__assign({}, documentSpan), { kind: "" /* ScriptElementKind.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 === 205 /* SyntaxKind.ObjectLiteralExpression */) { return { kind: "interface" /* ScriptElementKind.interfaceElement */, displayParts: [ts.punctuationPart(20 /* SyntaxKind.OpenParenToken */), ts.textPart("object literal"), ts.punctuationPart(21 /* SyntaxKind.CloseParenToken */)] }; } else if (node.kind === 226 /* SyntaxKind.ClassExpression */) { return { kind: "local class" /* ScriptElementKind.localClassElement */, displayParts: [ts.punctuationPart(20 /* SyntaxKind.OpenParenToken */), ts.textPart("anonymous local class"), ts.punctuationPart(21 /* SyntaxKind.CloseParenToken */)] }; } else { return { kind: ts.getNodeKind(node), displayParts: [] }; } } function toHighlightSpan(entry) { var documentSpan = entryToDocumentSpan(entry); if (entry.kind === 0 /* EntryKind.Span */) { return { fileName: documentSpan.fileName, span: { textSpan: documentSpan.textSpan, kind: "reference" /* HighlightSpanKind.reference */ } }; } var writeAccess = isWriteAccessForReference(entry.node); var span = __assign({ textSpan: documentSpan.textSpan, kind: writeAccess ? "writtenReference" /* HighlightSpanKind.writtenReference */ : "reference" /* HighlightSpanKind.reference */, isInString: entry.kind === 2 /* EntryKind.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) && (end - start) > 2) { ts.Debug.assert(endNode === undefined); start += 1; end -= 1; } return ts.createTextSpanFromBounds(start, end); } function getTextSpanOfEntry(entry) { return entry.kind === 0 /* EntryKind.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 === 88 /* SyntaxKind.DefaultKeyword */ || ts.isWriteAccess(node); } /** Whether a reference, `node`, is a definition of the `target` symbol */ function isDeclarationOfSymbol(node, target) { var _a; if (!target) return false; var source = ts.getDeclarationFromName(node) || (node.kind === 88 /* SyntaxKind.DefaultKeyword */ ? node.parent : ts.isLiteralComputedPropertyDeclarationName(node) ? node.parent.parent : node.kind === 134 /* SyntaxKind.ConstructorKeyword */ && ts.isConstructorDeclaration(node.parent) ? node.parent.parent : undefined); var commonjsSource = source && ts.isBinaryExpression(source) ? source.left : undefined; return !!(source && ((_a = target.declarations) === null || _a === void 0 ? void 0 : _a.some(function (d) { return d === source || d === commonjsSource; }))); } /** * 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 & 16777216 /* NodeFlags.Ambient */)) return true; switch (decl.kind) { case 221 /* SyntaxKind.BinaryExpression */: case 203 /* SyntaxKind.BindingElement */: case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 88 /* SyntaxKind.DefaultKeyword */: case 260 /* SyntaxKind.EnumDeclaration */: case 299 /* SyntaxKind.EnumMember */: case 275 /* SyntaxKind.ExportSpecifier */: case 267 /* SyntaxKind.ImportClause */: // default import case 265 /* SyntaxKind.ImportEqualsDeclaration */: case 270 /* SyntaxKind.ImportSpecifier */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 338 /* SyntaxKind.JSDocCallbackTag */: case 345 /* SyntaxKind.JSDocTypedefTag */: case 285 /* SyntaxKind.JsxAttribute */: case 261 /* SyntaxKind.ModuleDeclaration */: case 264 /* SyntaxKind.NamespaceExportDeclaration */: case 268 /* SyntaxKind.NamespaceImport */: case 274 /* SyntaxKind.NamespaceExport */: case 164 /* SyntaxKind.Parameter */: case 297 /* SyntaxKind.ShorthandPropertyAssignment */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 163 /* SyntaxKind.TypeParameter */: return true; case 296 /* SyntaxKind.PropertyAssignment */: // In `({ x: y } = 0);`, `x` is not a write access. (Won't call this function for `y`.) return !ts.isArrayLiteralOrObjectLiteralDestructuringPattern(decl.parent); case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 171 /* SyntaxKind.Constructor */: case 169 /* SyntaxKind.MethodDeclaration */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: return !!decl.body; case 254 /* SyntaxKind.VariableDeclaration */: case 167 /* SyntaxKind.PropertyDeclaration */: return !!decl.initializer || ts.isCatchClause(decl.parent); case 168 /* SyntaxKind.MethodSignature */: case 166 /* SyntaxKind.PropertySignature */: case 347 /* SyntaxKind.JSDocPropertyTag */: case 340 /* SyntaxKind.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) { var _a, _b; if (options === void 0) { options = {}; } if (sourceFilesSet === void 0) { sourceFilesSet = new ts.Set(sourceFiles.map(function (f) { return f.fileName; })); } node = getAdjustedNode(node, options); if (ts.isSourceFile(node)) { var resolvedRef = ts.GoToDefinition.getReferenceAtPosition(node, position, program); if (!(resolvedRef === null || resolvedRef === void 0 ? void 0 : resolvedRef.file)) { return undefined; } var moduleSymbol = program.getTypeChecker().getMergedSymbol(resolvedRef.file.symbol); if (moduleSymbol) { return getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet); } var fileIncludeReasons = program.getFileIncludeReasons(); if (!fileIncludeReasons) { return undefined; } return [{ definition: { type: 5 /* DefinitionKind.TripleSlashReference */, reference: resolvedRef.reference, file: node }, references: getReferencesForNonModule(resolvedRef.file, fileIncludeReasons, program) || ts.emptyArray }]; } if (!options.implementations) { var special = getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken); if (special) { return special; } } var checker = program.getTypeChecker(); // constructors should use the class symbol, detected by name, if present var symbol = checker.getSymbolAtLocation(ts.isConstructorDeclaration(node) && node.parent.name || 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. if (!options.implementations && ts.isStringLiteralLike(node)) { if (ts.isModuleSpecifierLike(node)) { var fileIncludeReasons = program.getFileIncludeReasons(); var referencedFileName = (_b = (_a = node.getSourceFile().resolvedModules) === null || _a === void 0 ? void 0 : _a.get(node.text, ts.getModeForUsageLocation(node.getSourceFile(), node))) === null || _b === void 0 ? void 0 : _b.resolvedFileName; var referencedFile = referencedFileName ? program.getSourceFile(referencedFileName) : undefined; if (referencedFile) { return [{ definition: { type: 4 /* DefinitionKind.String */, node: node }, references: getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || ts.emptyArray }]; } // Fall through to string literal references. This is not very likely to return // anything useful, but I guess it's better than nothing, and there's an existing // test that expects this to happen (fourslash/cases/untypedModuleImport.ts). } return getReferencesForStringLiteral(node, sourceFiles, checker, cancellationToken); } return undefined; } if (symbol.escapedName === "export=" /* InternalSymbolName.ExportEquals */) { return getReferencedSymbolsForModule(program, symbol.parent, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet); } var moduleReferences = getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol, program, sourceFiles, cancellationToken, options, sourceFilesSet); if (moduleReferences && !(symbol.flags & 33554432 /* SymbolFlags.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 getAdjustedNode(node, options) { if (options.use === 1 /* FindReferencesUse.References */) { node = ts.getAdjustedReferenceLocation(node); } else if (options.use === 2 /* FindReferencesUse.Rename */) { node = ts.getAdjustedRenameLocation(node); } return node; } Core.getAdjustedNode = getAdjustedNode; function getReferencesForFileName(fileName, program, sourceFiles, sourceFilesSet) { var _a, _b; if (sourceFilesSet === void 0) { sourceFilesSet = new ts.Set(sourceFiles.map(function (f) { return f.fileName; })); } var moduleSymbol = (_a = program.getSourceFile(fileName)) === null || _a === void 0 ? void 0 : _a.symbol; if (moduleSymbol) { return ((_b = getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet)[0]) === null || _b === void 0 ? void 0 : _b.references) || ts.emptyArray; } var fileIncludeReasons = program.getFileIncludeReasons(); var referencedFile = program.getSourceFile(fileName); return referencedFile && fileIncludeReasons && getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || ts.emptyArray; } Core.getReferencesForFileName = getReferencesForFileName; function getReferencesForNonModule(referencedFile, refFileMap, program) { var entries; var references = refFileMap.get(referencedFile.path) || ts.emptyArray; for (var _i = 0, references_1 = references; _i < references_1.length; _i++) { var ref = references_1[_i]; if (ts.isReferencedFile(ref)) { var referencingFile = program.getSourceFileByPath(ref.file); var location = ts.getReferencedFileLocation(program.getSourceFileByPath, ref); if (ts.isReferenceFileLocation(location)) { entries = ts.append(entries, { kind: 0 /* EntryKind.Span */, fileName: referencingFile.fileName, textSpan: ts.createTextSpanFromRange(location) }); } } } return entries; } 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 /* SymbolFlags.Module */) && symbol.declarations && ts.find(symbol.declarations, ts.isSourceFile); if (!moduleSourceFile) return undefined; var exportEquals = symbol.exports.get("export=" /* InternalSymbolName.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_5 = function (entry) { if (!entry.definition || entry.definition.type !== 0 /* DefinitionKind.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 /* DefinitionKind.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_2 = references; _b < references_2.length; _b++) { var entry = references_2[_b]; _loop_5(entry); } } return result; } function getSourceFileIndexOfEntry(program, entry) { var sourceFile = entry.kind === 0 /* EntryKind.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 /* EntryKind.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 305 /* SyntaxKind.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 261 /* SyntaxKind.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 /* SymbolFlags.Transient */), "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration."); } } } var exported = symbol.exports.get("export=" /* InternalSymbolName.ExportEquals */); if (exported === null || exported === void 0 ? void 0 : exported.declarations) { 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, 93 /* SyntaxKind.ExportKeyword */, sourceFile)) : ts.getNameOfDeclaration(decl) || decl; references.push(nodeEntry(node)); } } } return references.length ? [{ definition: { type: 0 /* DefinitionKind.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 === 145 /* SyntaxKind.ReadonlyKeyword */ && ts.isTypeOperatorNode(node.parent) && node.parent.operator === 145 /* SyntaxKind.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 === 114 /* SyntaxKind.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 === 145 /* SyntaxKind.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 === 145 /* SyntaxKind.ReadonlyKeyword */ ? isReadonlyTypeOperator : undefined); } if (ts.isImportMeta(node.parent) && node.parent.name === node) { return getAllReferencesForImportMeta(sourceFiles, cancellationToken); } if (ts.isStaticModifier(node) && ts.isClassStaticBlockDeclaration(node.parent)) { return [{ definition: { type: 2 /* DefinitionKind.Keyword */, node: node }, references: [nodeEntry(node)] }]; } // 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 === 106 /* SyntaxKind.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 /* SemanticMeaning.All */; var result = []; var state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : 0 /* SpecialSearchKind.None */, checker, cancellationToken, searchMeaning, options, result); var exportSpecifier = !isForRenameWithPrefixAndSuffixText(options) || !symbol.declarations ? 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 === 88 /* SyntaxKind.DefaultKeyword */ && symbol.escapedName === "default" /* InternalSymbolName.Default */ && symbol.parent) { addReference(node, symbol, state); searchForImportsOfExport(node, symbol, { exportingModuleSymbol: symbol.parent, exportKind: 1 /* ExportKind.Default */ }, state); } else { var search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, options.use === 2 /* FindReferencesUse.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 171 /* SyntaxKind.Constructor */: case 134 /* SyntaxKind.ConstructorKeyword */: return 1 /* SpecialSearchKind.Constructor */; case 79 /* SyntaxKind.Identifier */: if (ts.isClassLike(node.parent)) { ts.Debug.assert(node.parent.name === node); return 2 /* SpecialSearchKind.Class */; } // falls through default: return 0 /* SpecialSearchKind.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 /* SymbolFlags.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 ".concat(ts.Debug.formatSyntaxKind(node.kind), ": ").concat(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 /* SymbolFlags.Module */ | 33554432 /* SymbolFlags.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 = new ts.Map(); /** * 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 /* FindReferencesUse.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 /* DefinitionKind.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 /* EntryKind.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] = new ts.Set()); var anyNewSymbols = false; for (var _i = 0, symbols_1 = symbols; _i < symbols_1.length; _i++) { var sym = symbols_1[_i]; anyNewSymbols = ts.tryAddToSet(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 /* ImportExport.Export */), state); } if (indirectUsers.length) { var indirectSearch = void 0; switch (exportInfo.exportKind) { case 0 /* ExportKind.Named */: indirectSearch = state.createSearch(exportLocation, exportSymbol, 1 /* ImportExport.Export */); break; case 1 /* ExportKind.Default */: // Search for a property access to '.default'. This can't be renamed. indirectSearch = state.options.use === 2 /* FindReferencesUse.Rename */ ? undefined : state.createSearch(exportLocation, exportSymbol, 1 /* ImportExport.Export */, { text: "default" }); break; case 2 /* ExportKind.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, new ts.Set(sourceFiles.map(function (f) { return f.fileName; })), checker, cancellationToken); var _a = importTracker(exportSymbol, { exportKind: isDefaultExport ? 1 /* ExportKind.Default */ : 0 /* ExportKind.Named */, exportingModuleSymbol: exportingModuleSymbol }, /*isForRename*/ false), importSearches = _a.importSearches, indirectUsers = _a.indirectUsers, singleReferences = _a.singleReferences; for (var _i = 0, importSearches_2 = importSearches; _i < importSearches_2.length; _i++) { var importLocation = importSearches_2[_i][0]; cb(importLocation); } for (var _b = 0, singleReferences_2 = singleReferences; _b < singleReferences_2.length; _b++) { var singleReference = singleReferences_2[_b]; if (ts.isIdentifier(singleReference) && ts.isImportTypeNode(singleReference.parent)) { cb(singleReference); } } for (var _c = 0, indirectUsers_2 = indirectUsers; _c < indirectUsers_2.length; _c++) { var indirectUser = indirectUsers_2[_c]; for (var _d = 0, _e = getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName); _d < _e.length; _d++) { var node = _e[_d]; // Import specifiers should be handled by importSearches var symbol = checker.getSymbolAtLocation(node); var hasExportAssignmentDeclaration = ts.some(symbol === null || symbol === void 0 ? void 0 : symbol.declarations, function (d) { return ts.tryCast(d, ts.isExportAssignment) ? true : false; }); if (ts.isIdentifier(node) && !ts.isImportOrExportSpecifier(node.parent) && (symbol === exportSymbol || hasExportAssignmentDeclaration)) { cb(node); } } } } Core.eachExportReference = eachExportReference; function shouldAddSingleReference(singleRef, state) { if (!hasMatchingMeaning(singleRef, state)) return false; if (state.options.use !== 2 /* FindReferencesUse.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" /* InternalSymbolName.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 /* ImportExport.Import */), state, state.includesSourceFile(exportingFile)); } } /** Search for all occurrences 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 === 213 /* SyntaxKind.FunctionExpression */ || valueDeclaration.kind === 226 /* SyntaxKind.ClassExpression */)) { return valueDeclaration; } if (!declarations) { return undefined; } // If this is private property or method, the scope is the containing class if (flags & (4 /* SymbolFlags.Property */ | 8192 /* SymbolFlags.Method */)) { var privateDeclaration = ts.find(declarations, function (d) { return ts.hasEffectiveModifier(d, 8 /* ModifierFlags.Private */) || ts.isPrivateIdentifierClassElementDeclaration(d); }); if (privateDeclaration) { return ts.getAncestor(privateDeclaration, 257 /* SyntaxKind.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 /* SymbolFlags.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 === 305 /* SyntaxKind.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; } scope = container; if (ts.isFunctionExpression(scope)) { var next = void 0; while (next = ts.getNextJSDocCommentLocation(scope)) { scope = next; } } } // 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); 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 getTopMostDeclarationNamesInFile(declarationName, sourceFile) { var candidates = ts.filter(getPossibleSymbolReferenceNodes(sourceFile, declarationName), function (name) { return !!ts.getDeclarationFromName(name); }); return candidates.reduce(function (topMost, decl) { var depth = getDepth(decl); if (!ts.some(topMost.declarationNames) || depth === topMost.depth) { topMost.declarationNames.push(decl); topMost.depth = depth; } else if (depth < topMost.depth) { topMost.declarationNames = [decl]; topMost.depth = depth; } return topMost; }, { depth: Infinity, declarationNames: [] }).declarationNames; function getDepth(declaration) { var depth = 0; while (declaration) { declaration = ts.getContainerNode(declaration); depth++; } return depth; } } Core.getTopMostDeclarationNamesInFile = getTopMostDeclarationNamesInFile; function someSignatureUsage(signature, sourceFiles, checker, cb) { if (!signature.name || !ts.isIdentifier(signature.name)) return false; 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 = ts.isCallExpression(called.parent) && called.parent.expression === called ? called.parent : undefined; var referenceSymbol = checker.getSymbolAtLocation(name); if (referenceSymbol && checker.getRootSymbols(referenceSymbol).some(function (s) { return s === symbol; })) { if (cb(name, call)) { return true; } } } } return false; } Core.someSignatureUsage = someSignatureUsage; 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 /* ScriptTarget.Latest */)) && (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 99 /* ScriptTarget.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 /* DefinitionKind.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 80 /* SyntaxKind.PrivateIdentifier */: if (ts.isJSDocMemberName(node.parent)) { return true; } // falls through I guess case 79 /* SyntaxKind.Identifier */: return node.text.length === searchSymbolName.length; case 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */: case 10 /* SyntaxKind.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 /* SyntaxKind.NumericLiteral */: return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && node.text.length === searchSymbolName.length; case 88 /* SyntaxKind.DefaultKeyword */: return "default".length === searchSymbolName.length; default: return false; } } function getAllReferencesForImportMeta(sourceFiles, cancellationToken) { var references = ts.flatMap(sourceFiles, function (sourceFile) { cancellationToken.throwIfCancellationRequested(); return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "meta", sourceFile), function (node) { var parent = node.parent; if (ts.isImportMeta(parent)) { return nodeEntry(parent); } }); }); return references.length ? [{ definition: { type: 2 /* DefinitionKind.Keyword */, node: references[0].node }, references: references }] : undefined; } 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 /* DefinitionKind.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 === 79 /* SyntaxKind.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 /* SpecialSearchKind.None */: if (addReferencesHere) addReference(referenceLocation, relatedSymbol, state); break; case 1 /* SpecialSearchKind.Constructor */: addConstructorReferences(referenceLocation, sourceFile, search, state); break; case 2 /* SpecialSearchKind.Class */: addClassStaticThisReferences(referenceLocation, search, state); break; default: ts.Debug.assertNever(state.specialSearchKind); } // Use the parent symbol if the location is commonjs require syntax on javascript files only. if (ts.isInJSFile(referenceLocation) && referenceLocation.parent.kind === 203 /* SyntaxKind.BindingElement */ && ts.isVariableDeclarationInitializedToBareOrAccessedRequire(referenceLocation.parent.parent.parent)) { referenceSymbol = referenceLocation.parent.symbol; // The parent will not have a symbol if it's an ObjectBindingPattern (when destructuring is used). In // this case, just skip it, since the bound identifiers are not an alias of the import. if (!referenceSymbol) return; } 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 /* FindReferencesUse.Rename */ && (name.escapedText === "default" /* InternalSymbolName.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 /* FindReferencesUse.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 === 88 /* SyntaxKind.DefaultKeyword */ || exportSpecifier.name.originalKeywordKind === 88 /* SyntaxKind.DefaultKeyword */; var exportKind = isDefaultExport ? 1 /* ExportKind.Default */ : 0 /* ExportKind.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 /* ImportExport.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 /* ImportExport.Export */); if (!importOrExport) return; var symbol = importOrExport.symbol; if (importOrExport.kind === 0 /* ImportExport.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 /* SymbolFlags.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 // if rename symbol from default export anonymous function, for example `export default function() {}`, we do not need to add reference if (state.options.use === 2 /* FindReferencesUse.Rename */ && referenceLocation.kind === 88 /* SyntaxKind.DefaultKeyword */) { return; } 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 === 88 /* SyntaxKind.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 /* FindReferencesUse.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.isStatic(member))) { continue; } if (member.body) { member.body.forEachChild(function cb(node) { if (node.kind === 108 /* SyntaxKind.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, 134 /* SyntaxKind.ConstructorKeyword */, sourceFile); ts.Debug.assert(decl.kind === 171 /* SyntaxKind.Constructor */ && !!ctrKeyword); addNode(ctrKeyword); } } if (classSymbol.exports) { classSymbol.exports.forEach(function (member) { var decl = member.valueDeclaration; if (decl && decl.kind === 169 /* SyntaxKind.MethodDeclaration */) { var body = decl.body; if (body) { forEachDescendantOfKind(body, 108 /* SyntaxKind.ThisKeyword */, function (thisKeyword) { if (ts.isNewExpressionTarget(thisKeyword)) { addNode(thisKeyword); } }); } } }); } } function getClassConstructorSymbol(classSymbol) { return classSymbol.members && classSymbol.members.get("__constructor" /* InternalSymbolName.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 === 171 /* SyntaxKind.Constructor */); var body = decl.body; if (body) { forEachDescendantOfKind(body, 106 /* SyntaxKind.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 !== 79 /* SyntaxKind.Identifier */) { return; } if (refNode.parent.kind === 297 /* SyntaxKind.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 === 235 /* SyntaxKind.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 212 /* SyntaxKind.ParenthesizedExpression */: return isImplementationExpression(node.expression); case 214 /* SyntaxKind.ArrowFunction */: case 213 /* SyntaxKind.FunctionExpression */: case 205 /* SyntaxKind.ObjectLiteralExpression */: case 226 /* SyntaxKind.ClassExpression */: case 204 /* SyntaxKind.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 /* ModifierFlags.Static */; switch (searchSpaceNode.kind) { case 167 /* SyntaxKind.PropertyDeclaration */: case 166 /* SyntaxKind.PropertySignature */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: case 171 /* SyntaxKind.Constructor */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: staticFlag &= ts.getSyntacticModifierFlags(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 !== 106 /* SyntaxKind.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 && ts.isStatic(container) === !!staticFlag && container.parent.symbol === searchSpaceNode.symbol ? nodeEntry(node) : undefined; }); return [{ definition: { type: 0 /* DefinitionKind.Symbol */, symbol: searchSpaceNode.symbol }, references: references }]; } function isParameterName(node) { return node.kind === 79 /* SyntaxKind.Identifier */ && node.parent.kind === 164 /* SyntaxKind.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 /* ModifierFlags.Static */; switch (searchSpaceNode.kind) { case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: if (ts.isObjectLiteralMethod(searchSpaceNode)) { staticFlag &= ts.getSyntacticModifierFlags(searchSpaceNode); searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning object literals break; } // falls through case 167 /* SyntaxKind.PropertyDeclaration */: case 166 /* SyntaxKind.PropertySignature */: case 171 /* SyntaxKind.Constructor */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: staticFlag &= ts.getSyntacticModifierFlags(searchSpaceNode); searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; case 305 /* SyntaxKind.SourceFile */: if (ts.isExternalModule(searchSpaceNode) || isParameterName(thisOrSuperKeyword)) { return undefined; } // falls through case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.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 === 305 /* SyntaxKind.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 213 /* SyntaxKind.FunctionExpression */: case 256 /* SyntaxKind.FunctionDeclaration */: return searchSpaceNode.symbol === container.symbol; case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: return ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol; case 226 /* SyntaxKind.ClassExpression */: case 257 /* SyntaxKind.ClassDeclaration */: case 205 /* SyntaxKind.ObjectLiteralExpression */: // Make sure the container belongs to the same class/object literals // and has the appropriate static modifier from the original container. return container.parent && searchSpaceNode.symbol === container.parent.symbol && ts.isStatic(container) === !!staticFlag; case 305 /* SyntaxKind.SourceFile */: return container.kind === 305 /* SyntaxKind.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 /* DefinitionKind.This */, node: thisParameter || thisOrSuperKeyword }, references: references }]; } function getReferencesForStringLiteral(node, sourceFiles, checker, cancellationToken) { var type = ts.getContextualTypeFromParentOrAncestorTypeNode(node, checker); var references = ts.flatMap(sourceFiles, function (sourceFile) { cancellationToken.throwIfCancellationRequested(); return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), function (ref) { if (ts.isStringLiteralLike(ref) && ref.text === node.text) { if (type) { var refType = ts.getContextualTypeFromParentOrAncestorTypeNode(ref, checker); if (type !== checker.getStringType() && type === refType) { return nodeEntry(ref, 2 /* EntryKind.StringLiteral */); } } else { return ts.isNoSubstitutionTemplateLiteral(ref) && !ts.rangeIsOnSingleLine(ref, sourceFile) ? undefined : nodeEntry(ref, 2 /* EntryKind.StringLiteral */); } } }); }); return [{ definition: { type: 4 /* DefinitionKind.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) { // static method/property and instance method/property might have the same name. Only include static or only include instance. if (base) { if (isStaticSymbol(symbol) !== isStaticSymbol(base)) { base = undefined; } } result.push(base || root || sym); }, // when try to find implementation, implementations is true, and not allowed to find base class /*allowBaseTypes*/ function () { return !implementations; }); return result; } /** * @param allowBaseTypes return true means it would try to find in base class or interface. */ function forEachRelatedSymbol(symbol, location, checker, isForRenamePopulateSearchSymbolSet, onlyIncludeBindingElementAtReferenceLocation, /** * @param baseSymbol This symbol means one property/mehtod from base class or interface when it is not null or undefined, */ 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 /* EntryKind.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 /* EntryKind.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 /* EntryKind.SearchedPropertyFoundLocal */); if (res1) return res1; var res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, 3 /* EntryKind.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 /* EntryKind.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 /* SymbolFlags.FunctionScopedVariable */) && !!(paramProps[1].flags & 4 /* SymbolFlags.Property */)); // is [parameter, property] return fromRoot(symbol.flags & 1 /* SymbolFlags.FunctionScopedVariable */ ? paramProps[1] : paramProps[0]); } var exportSpecifier = ts.getDeclarationOfKind(symbol, 275 /* SyntaxKind.ExportSpecifier */); if (!isForRenamePopulateSearchSymbolSet || exportSpecifier && !exportSpecifier.propertyName) { var localSymbol = exportSpecifier && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier); if (localSymbol) { var res_3 = cbSymbol(localSymbol, /*rootSymbol*/ undefined, /*baseSymbol*/ undefined, 1 /* EntryKind.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 /* EntryKind.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 /* EntryKind.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 /* SymbolFlags.Class */ | 64 /* SymbolFlags.Interface */) && allowBaseTypes(rootSymbol) ? getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, function (base) { return cbSymbol(sym, rootSymbol, base, kind); }) : undefined); }); } function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker) { var bindingElement = ts.getDeclarationOfKind(symbol, 203 /* SyntaxKind.BindingElement */); if (bindingElement && ts.isObjectBindingElementWithoutPropertyName(bindingElement)) { return ts.getPropertySymbolFromBindingElement(checker, bindingElement); } } } /** * Find symbol of the given property-name and add the symbol to the given result array * @param symbol a symbol to start searching for the given propertyName * @param propertyName a name of property to search for * @param result an array of symbol of found property symbols * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. * The value of previousIterationSymbol is undefined when the function is first called. */ function getPropertySymbolsFromBaseTypes(symbol, propertyName, checker, cb) { var seen = new ts.Map(); return recur(symbol); function recur(symbol) { // Use `addToSeen` to ensure we don't infinitely recurse in this situation: // interface C extends C { // /*findRef*/propName: string; // } if (!(symbol.flags & (32 /* SymbolFlags.Class */ | 64 /* SymbolFlags.Interface */)) || !ts.addToSeen(seen, ts.getSymbolId(symbol))) return; return ts.firstDefined(symbol.declarations, function (declaration) { return ts.firstDefined(ts.getAllSuperTypeNodes(declaration), function (typeReference) { var type = checker.getTypeAtLocation(typeReference); var propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName); // Visit the typeReference as well to see if it directly or indirectly uses that property return type && propertySymbol && (ts.firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol)); }); }); } } function isStaticSymbol(symbol) { if (!symbol.valueDeclaration) return false; var modifierFlags = ts.getEffectiveModifierFlags(symbol.valueDeclaration); return !!(modifierFlags & 32 /* ModifierFlags.Static */); } function getRelatedSymbol(search, referenceSymbol, referenceLocation, state) { var checker = state.checker; return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false, /*onlyIncludeBindingElementAtReferenceLocation*/ state.options.use !== 2 /* FindReferencesUse.Rename */ || !!state.options.providePrefixAndSuffixTextForRename, function (sym, rootSymbol, baseSymbol, kind) { // check whether the symbol used to search itself is just the searched one. if (baseSymbol) { // static method/property and instance method/property might have the same name. Only check static or only check instance. if (isStaticSymbol(referenceSymbol) !== isStaticSymbol(baseSymbol)) { baseSymbol = undefined; } } 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 /* CheckFlags.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 & 16777216 /* NodeFlags.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 /* SemanticMeaning.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 /* SymbolFlags.Class */ | 64 /* SymbolFlags.Interface */) ? t.symbol : undefined; }); return res.length === 0 ? undefined : res; } function isForRenameWithPrefixAndSuffixText(options) { return options.use === 2 /* FindReferencesUse.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 /* NodeFlags.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.isClassStaticBlockDeclaration(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.isClassStaticBlockDeclaration(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 === 88 /* SyntaxKind.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() }; } } if (ts.isClassStaticBlockDeclaration(node)) { var sourceFile = node.getSourceFile(); var pos = ts.skipTrivia(sourceFile.text, ts.moveRangePastModifiers(node).pos); var end = pos + 6; /* "static".length */ var typeChecker = program.getTypeChecker(); var symbol = typeChecker.getSymbolAtLocation(node.parent); var prefix = symbol ? "".concat(typeChecker.symbolToString(symbol, node.parent), " ") : ""; return { text: "".concat(prefix, "static {}"), pos: pos, end: end }; } 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 /* EmitHint.Unspecified */, node, node.getSourceFile(), writer); }); } return { text: text, pos: declName.getStart(), end: declName.getEnd() }; } function getCallHierarchItemContainerName(node) { var _a, _b; if (isConstNamedExpression(node)) { if (ts.isModuleBlock(node.parent.parent.parent.parent) && ts.isIdentifier(node.parent.parent.parent.parent.parent.name)) { return node.parent.parent.parent.parent.parent.name.getText(); } return; } switch (node.kind) { case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: case 169 /* SyntaxKind.MethodDeclaration */: if (node.parent.kind === 205 /* SyntaxKind.ObjectLiteralExpression */) { return (_a = ts.getAssignedName(node.parent)) === null || _a === void 0 ? void 0 : _a.getText(); } return (_b = ts.getNameOfDeclaration(node.parent)) === null || _b === void 0 ? void 0 : _b.getText(); case 256 /* SyntaxKind.FunctionDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: if (ts.isModuleBlock(node.parent) && ts.isIdentifier(node.parent.parent.name)) { return node.parent.parent.name.getText(); } } } 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.isClassStaticBlockDeclaration(node)) { return node; } 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, Class Static Block, 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 // - Class `static {}` initializer blocks // - 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 (location.kind === 124 /* SyntaxKind.StaticKeyword */ && ts.isClassStaticBlockDeclaration(location.parent)) { location = location.parent; continue; } // #39453 if (ts.isVariableDeclaration(location) && location.initializer && isConstNamedExpression(location.initializer)) { return location.initializer; } if (!followingSymbol) { var symbol = typeChecker.getSymbolAtLocation(location); if (symbol) { if (symbol.flags & 2097152 /* SymbolFlags.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 containerName = getCallHierarchItemContainerName(node); var kind = ts.getNodeKind(node); var kindModifiers = ts.getNodeModifiers(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, kindModifiers: kindModifiers, name: name.text, containerName: containerName, span: span, selectionSpan: selectionSpan }; } CallHierarchy.createCallHierarchyItem = createCallHierarchyItem; function isDefined(x) { return x !== undefined; } function convertEntryToCallSite(entry) { if (entry.kind === 1 /* FindAllReferences.EntryKind.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) || ts.isClassStaticBlockDeclaration(declaration)) { return []; } var location = getCallHierarchyDeclarationReferenceNode(declaration); var calls = ts.filter(ts.FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, program.getSourceFiles(), location, /*position*/ 0, { use: 1 /* FindAllReferences.FindReferencesUse.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 : ts.isClassStaticBlockDeclaration(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 & 16777216 /* NodeFlags.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 79 /* SyntaxKind.Identifier */: case 265 /* SyntaxKind.ImportEqualsDeclaration */: case 266 /* SyntaxKind.ImportDeclaration */: case 272 /* SyntaxKind.ExportDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: // do not descend into nodes that cannot contain callable nodes return; case 170 /* SyntaxKind.ClassStaticBlockDeclaration */: recordCallSite(node); return; case 211 /* SyntaxKind.TypeAssertionExpression */: case 229 /* SyntaxKind.AsExpression */: // do not descend into the type side of an assertion collect(node.expression); return; case 254 /* SyntaxKind.VariableDeclaration */: case 164 /* SyntaxKind.Parameter */: // do not descend into the type of a variable or parameter declaration collect(node.name); collect(node.initializer); return; case 208 /* SyntaxKind.CallExpression */: // do not descend into the type arguments of a call expression recordCallSite(node); collect(node.expression); ts.forEach(node.arguments, collect); return; case 209 /* SyntaxKind.NewExpression */: // do not descend into the type arguments of a new expression recordCallSite(node); collect(node.expression); ts.forEach(node.arguments, collect); return; case 210 /* SyntaxKind.TaggedTemplateExpression */: // do not descend into the type arguments of a tagged template expression recordCallSite(node); collect(node.tag); collect(node.template); return; case 280 /* SyntaxKind.JsxOpeningElement */: case 279 /* SyntaxKind.JsxSelfClosingElement */: // do not descend into the type arguments of a JsxOpeningLikeElement recordCallSite(node); collect(node.tagName); collect(node.attributes); return; case 165 /* SyntaxKind.Decorator */: recordCallSite(node); collect(node.expression); return; case 206 /* SyntaxKind.PropertyAccessExpression */: case 207 /* SyntaxKind.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.hasSyntacticModifier(node, 2 /* ModifierFlags.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 collectCallSitesOfClassStaticBlockDeclaration(node, collect) { collect(node.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); } else if (ts.isClassStaticBlockDeclaration(member)) { collect(member); } } } function collectCallSites(program, node) { var callSites = []; var collect = createCallSiteCollector(program, callSites); switch (node.kind) { case 305 /* SyntaxKind.SourceFile */: collectCallSitesOfSourceFile(node, collect); break; case 261 /* SyntaxKind.ModuleDeclaration */: collectCallSitesOfModuleDeclaration(node, collect); break; case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: case 169 /* SyntaxKind.MethodDeclaration */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: collectCallSitesOfFunctionLikeDeclaration(program.getTypeChecker(), node, collect); break; case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: collectCallSitesOfClassLikeDeclaration(node, collect); break; case 170 /* SyntaxKind.ClassStaticBlockDeclaration */: collectCallSitesOfClassStaticBlockDeclaration(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 & 16777216 /* NodeFlags.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)) return; var includes = ts.mapDefined(property.initializer.elements, function (e) { return ts.isStringLiteral(e) ? e.text : undefined; }); if (includes.length === 0) return; 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.factory.createStringLiteral(relativePath(newFileOrDirPath))); } return; } 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); } }); } }); return; } }); function updatePaths(property) { 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_6 = function (sourceFile) { var newFromOld = oldToNew(sourceFile.fileName); var newImportFromPath = newFromOld !== null && newFromOld !== void 0 ? newFromOld : sourceFile.fileName; 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 === null || importedModuleSymbol === void 0 ? void 0 : importedModuleSymbol.declarations) && 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(importLiteral, 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(), sourceFile, getCanonicalFileName(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_6(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 mode = ts.getModeForUsageLocation(importingSourceFile, importLiteral); var resolved = host.resolveModuleNames ? host.getResolvedModuleWithFailedLookupLocationsFromCache && host.getResolvedModuleWithFailedLookupLocationsFromCache(importLiteral.text, importingSourceFile.fileName, mode) : program.getResolvedModuleWithFailedLookupLocationsFromCache(importLiteral.text, importingSourceFile.fileName, mode); return getSourceFileToImportFromResolved(importLiteral, resolved, oldToNew, program.getSourceFiles()); } } function getSourceFileToImportFromResolved(importLiteral, 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_3 = tryChange(resolved.resolvedModule.resolvedFileName); if (result_3) return result_3; } // 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). // At this point, the confidence level of this fix being correct is too low to change bare specifiers or absolute paths. || ts.pathIsRelative(importLiteral.text) && 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, searchOtherFilesOnly, stopAtAlias) { var _a; var _b; var resolvedRef = getReferenceAtPosition(sourceFile, position, program); var fileReferenceDefinition = resolvedRef && [getDefinitionInfoForFileReference(resolvedRef.reference.fileName, resolvedRef.fileName, resolvedRef.unverified)] || ts.emptyArray; if (resolvedRef === null || resolvedRef === void 0 ? void 0 : resolvedRef.file) { // If `file` is missing, do a symbol-based lookup as well return fileReferenceDefinition; } var node = ts.getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { return undefined; } var parent = node.parent; var typeChecker = program.getTypeChecker(); if (node.kind === 159 /* SyntaxKind.OverrideKeyword */ || (ts.isJSDocOverrideTag(node) && ts.rangeContainsPosition(node.tagName, position))) { return getDefinitionFromOverriddenMember(typeChecker, node) || ts.emptyArray; } // Labels if (ts.isJumpStatementTarget(node)) { var label = ts.getTargetLabel(node.parent, node.text); return label ? [createDefinitionInfoFromName(typeChecker, label, "label" /* ScriptElementKind.label */, node.text, /*containerName*/ undefined)] : undefined; // TODO: GH#18217 } if (ts.isStaticModifier(node) && ts.isClassStaticBlockDeclaration(node.parent)) { var classDecl = node.parent.parent; var _c = getSymbol(classDecl, typeChecker, stopAtAlias), symbol_1 = _c.symbol, failedAliasResolution_1 = _c.failedAliasResolution; var staticBlocks = ts.filter(classDecl.members, ts.isClassStaticBlockDeclaration); var containerName_1 = symbol_1 ? typeChecker.symbolToString(symbol_1, classDecl) : ""; var sourceFile_1 = node.getSourceFile(); return ts.map(staticBlocks, function (staticBlock) { var pos = ts.moveRangePastModifiers(staticBlock).pos; pos = ts.skipTrivia(sourceFile_1.text, pos); return createDefinitionInfoFromName(typeChecker, staticBlock, "constructor" /* ScriptElementKind.constructorImplementationElement */, "static {}", containerName_1, /*unverified*/ false, failedAliasResolution_1, { start: pos, length: "static".length }); }); } var _d = getSymbol(node, typeChecker, stopAtAlias), symbol = _d.symbol, failedAliasResolution = _d.failedAliasResolution; var fallbackNode = node; if (searchOtherFilesOnly && failedAliasResolution) { // We couldn't resolve the specific import, try on the module specifier. var importDeclaration = ts.forEach(__spreadArray([node], (symbol === null || symbol === void 0 ? void 0 : symbol.declarations) || ts.emptyArray, true), function (n) { return ts.findAncestor(n, ts.isAnyImportOrBareOrAccessedRequire); }); var moduleSpecifier = importDeclaration && ts.tryGetModuleSpecifierFromDeclaration(importDeclaration); if (moduleSpecifier) { (_a = getSymbol(moduleSpecifier, typeChecker, stopAtAlias), symbol = _a.symbol, failedAliasResolution = _a.failedAliasResolution); fallbackNode = moduleSpecifier; } } if (!symbol && ts.isModuleSpecifierLike(fallbackNode)) { // We couldn't resolve the module specifier as an external module, but it could // be that module resolution succeeded but the target was not a module. var ref = (_b = sourceFile.resolvedModules) === null || _b === void 0 ? void 0 : _b.get(fallbackNode.text, ts.getModeForUsageLocation(sourceFile, fallbackNode)); if (ref) { return [{ name: fallbackNode.text, fileName: ref.resolvedFileName, containerName: undefined, containerKind: undefined, kind: "script" /* ScriptElementKind.scriptElement */, textSpan: ts.createTextSpan(0, 0), failedAliasResolution: failedAliasResolution, isAmbient: ts.isDeclarationFileName(ref.resolvedFileName), unverified: fallbackNode !== node, }]; } } // 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 ts.concatenate(fileReferenceDefinition, getDefinitionInfoForIndexSignatures(node, typeChecker)); } if (searchOtherFilesOnly && ts.every(symbol.declarations, function (d) { return d.getSourceFile().fileName === sourceFile.fileName; })) return undefined; 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, failedAliasResolution); // 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); })) { return [sigInfo]; } else { var defs = getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, calledDeclaration) || ts.emptyArray; // For a 'super()' call, put the signature first, else put the variable first. return node.kind === 106 /* SyntaxKind.SuperKeyword */ ? __spreadArray([sigInfo], defs, true) : __spreadArray(__spreadArray([], defs, true), [sigInfo], false); } } // 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 === 297 /* SyntaxKind.ShorthandPropertyAssignment */) { var shorthandSymbol_1 = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); var definitions = (shorthandSymbol_1 === null || shorthandSymbol_1 === void 0 ? void 0 : shorthandSymbol_1.declarations) ? shorthandSymbol_1.declarations.map(function (decl) { return createDefinitionInfo(decl, typeChecker, shorthandSymbol_1, node, /*unverified*/ false, failedAliasResolution); }) : ts.emptyArray; return ts.concatenate(definitions, getDefinitionFromObjectLiteralElement(typeChecker, node) || ts.emptyArray); } // 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); }); } return ts.concatenate(fileReferenceDefinition, getDefinitionFromObjectLiteralElement(typeChecker, node) || getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution)); } 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;`. * Also true for any assignment RHS. */ function symbolMatchesSignature(s, calledDeclaration) { return s === calledDeclaration.symbol || s === calledDeclaration.symbol.parent || ts.isAssignmentExpression(calledDeclaration.parent) || (!ts.isCallLikeExpression(calledDeclaration.parent) && s === calledDeclaration.parent.symbol); } // 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 }) function getDefinitionFromObjectLiteralElement(typeChecker, node) { 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); }); } } } function getDefinitionFromOverriddenMember(typeChecker, node) { var classElement = ts.findAncestor(node, ts.isClassElement); if (!(classElement && classElement.name)) return; var baseDeclaration = ts.findAncestor(classElement, ts.isClassLike); if (!baseDeclaration) return; var baseTypeNode = ts.getEffectiveBaseTypeNode(baseDeclaration); var baseType = baseTypeNode ? typeChecker.getTypeAtLocation(baseTypeNode) : undefined; if (!baseType) return; var name = ts.unescapeLeadingUnderscores(ts.getTextOfPropertyName(classElement.name)); var symbol = ts.hasStaticModifier(classElement) ? typeChecker.getPropertyOfType(typeChecker.getTypeOfSymbolAtLocation(baseType.symbol, baseDeclaration), name) : typeChecker.getPropertyOfType(baseType, name); if (!symbol) return; return getDefinitionFromSymbol(typeChecker, symbol, node); } function getReferenceAtPosition(sourceFile, position, program) { var _a, _b; var referencePath = findReferenceInPosition(sourceFile.referencedFiles, position); if (referencePath) { var file = program.getSourceFileFromReference(sourceFile, referencePath); return file && { reference: referencePath, fileName: file.fileName, file: file, unverified: false }; } var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position); if (typeReferenceDirective) { var reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName, typeReferenceDirective.resolutionMode || sourceFile.impliedNodeFormat); var file = reference && program.getSourceFile(reference.resolvedFileName); // TODO:GH#18217 return file && { reference: typeReferenceDirective, fileName: file.fileName, file: file, unverified: false }; } var libReferenceDirective = findReferenceInPosition(sourceFile.libReferenceDirectives, position); if (libReferenceDirective) { var file = program.getLibFileFromReference(libReferenceDirective); return file && { reference: libReferenceDirective, fileName: file.fileName, file: file, unverified: false }; } if ((_a = sourceFile.resolvedModules) === null || _a === void 0 ? void 0 : _a.size()) { var node = ts.getTouchingToken(sourceFile, position); if (ts.isModuleSpecifierLike(node) && ts.isExternalModuleNameRelative(node.text) && sourceFile.resolvedModules.has(node.text, ts.getModeForUsageLocation(sourceFile, node))) { var verifiedFileName = (_b = sourceFile.resolvedModules.get(node.text, ts.getModeForUsageLocation(sourceFile, node))) === null || _b === void 0 ? void 0 : _b.resolvedFileName; var fileName = verifiedFileName || ts.resolvePath(ts.getDirectoryPath(sourceFile.fileName), node.text); return { file: program.getSourceFile(fileName), fileName: fileName, reference: { pos: node.getStart(), end: node.getEnd(), fileName: node.text }, unverified: !verifiedFileName, }; } } return undefined; } GoToDefinition.getReferenceAtPosition = getReferenceAtPosition; /// Goto type function getTypeDefinitionAtPosition(typeChecker, sourceFile, position) { var node = ts.getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { return undefined; } if (ts.isImportMeta(node.parent) && node.parent.name === node) { return definitionFromType(typeChecker.getTypeAtLocation(node.parent), typeChecker, node.parent, /*failedAliasResolution*/ false); } var _a = getSymbol(node, typeChecker, /*stopAtAlias*/ false), symbol = _a.symbol, failedAliasResolution = _a.failedAliasResolution; if (!symbol) return undefined; var typeAtLocation = typeChecker.getTypeOfSymbolAtLocation(symbol, node); var returnType = tryGetReturnTypeOfFunction(symbol, typeAtLocation, typeChecker); var fromReturnType = returnType && definitionFromType(returnType, typeChecker, node, failedAliasResolution); // If a function returns 'void' or some other type with no definition, just return the function definition. var typeDefinitions = fromReturnType && fromReturnType.length !== 0 ? fromReturnType : definitionFromType(typeAtLocation, typeChecker, node, failedAliasResolution); return typeDefinitions.length ? typeDefinitions : !(symbol.flags & 111551 /* SymbolFlags.Value */) && symbol.flags & 788968 /* SymbolFlags.Type */ ? getDefinitionFromSymbol(typeChecker, ts.skipAlias(symbol, typeChecker), node, failedAliasResolution) : undefined; } GoToDefinition.getTypeDefinitionAtPosition = getTypeDefinitionAtPosition; function definitionFromType(type, checker, node, failedAliasResolution) { return ts.flatMap(type.isUnion() && !(type.flags & 32 /* TypeFlags.Enum */) ? type.types : [type], function (t) { return t.symbol && getDefinitionFromSymbol(checker, t.symbol, node, failedAliasResolution); }); } 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) { return ts.mapDefined(checker.getIndexInfosAtLocation(node), function (info) { return info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration); }); } function getSymbol(node, checker, stopAtAlias) { 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. var failedAliasResolution = false; if ((symbol === null || symbol === void 0 ? void 0 : symbol.declarations) && symbol.flags & 2097152 /* SymbolFlags.Alias */ && !stopAtAlias && shouldSkipAlias(node, symbol.declarations[0])) { var aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { return { symbol: aliased }; } else { failedAliasResolution = true; } } return { symbol: symbol, failedAliasResolution: failedAliasResolution }; } // 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 !== 79 /* SyntaxKind.Identifier */) { return false; } if (node.parent === declaration) { return true; } if (declaration.kind === 268 /* SyntaxKind.NamespaceImport */) { return false; } return true; } /** * ```ts * function f() {} * f.foo = 0; * ``` * * Here, `f` has two declarations: the function declaration, and the identifier in the next line. * The latter is a declaration for `f` because it gives `f` the `SymbolFlags.Namespace` meaning so * it can contain `foo`. However, that declaration is pretty uninteresting and not intuitively a * "definition" for `f`. Ideally, the question we'd like to answer is "what SymbolFlags does this * declaration contribute to the symbol for `f`?" If the answer is just `Namespace` and the * declaration looks like an assignment, that declaration is in no sense a definition for `f`. * But that information is totally lost during binding and/or symbol merging, so we need to do * our best to reconstruct it or use other heuristics. This function (and the logic around its * calling) covers our tests but feels like a hack, and it would be great if someone could come * up with a more precise definition of what counts as a definition. */ function isExpandoDeclaration(node) { if (!ts.isAssignmentDeclaration(node)) return false; var containingAssignment = ts.findAncestor(node, function (p) { if (ts.isAssignmentExpression(p)) return true; if (!ts.isAssignmentDeclaration(p)) return "quit"; return false; }); return !!containingAssignment && ts.getAssignmentDeclarationKind(containingAssignment) === 5 /* AssignmentDeclarationKind.Property */; } function getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, excludeDeclaration) { var filteredDeclarations = ts.filter(symbol.declarations, function (d) { return d !== excludeDeclaration; }); var withoutExpandos = ts.filter(filteredDeclarations, function (d) { return !isExpandoDeclaration(d); }); var results = ts.some(withoutExpandos) ? withoutExpandos : filteredDeclarations; return getConstructSignatureDefinition() || getCallSignatureDefinition() || ts.map(results, function (declaration) { return createDefinitionInfo(declaration, typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution); }); 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 /* SymbolFlags.Class */ && !(symbol.flags & (16 /* SymbolFlags.Function */ | 3 /* SymbolFlags.Variable */)) && (ts.isNewExpressionTarget(node) || node.kind === 134 /* SyntaxKind.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, /*unverified*/ false, failedAliasResolution)] : undefined; } } /** Creates a DefinitionInfo from a Declaration, using the declaration's name if possible. */ function createDefinitionInfo(declaration, checker, symbol, node, unverified, failedAliasResolution) { 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, unverified, failedAliasResolution); } GoToDefinition.createDefinitionInfo = createDefinitionInfo; /** Creates a DefinitionInfo directly from the name of a declaration. */ function createDefinitionInfoFromName(checker, declaration, symbolKind, symbolName, containerName, unverified, failedAliasResolution, textSpan) { var sourceFile = declaration.getSourceFile(); if (!textSpan) { var name = ts.getNameOfDeclaration(declaration) || declaration; 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: !isDefinitionVisible(checker, declaration), isAmbient: !!(declaration.flags & 16777216 /* NodeFlags.Ambient */), unverified: unverified, failedAliasResolution: failedAliasResolution }); } function isDefinitionVisible(checker, declaration) { if (checker.isDeclarationVisible(declaration)) return true; if (!declaration.parent) return false; // Variable initializers are visible if variable is visible if (ts.hasInitializer(declaration.parent) && declaration.parent.initializer === declaration) return isDefinitionVisible(checker, declaration.parent); // Handle some exceptions here like arrow function, members of class and object literal expression which are technically not visible but we want the definition to be determined by its parent switch (declaration.kind) { case 167 /* SyntaxKind.PropertyDeclaration */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: case 169 /* SyntaxKind.MethodDeclaration */: // Private/protected properties/methods are not visible if (ts.hasEffectiveModifier(declaration, 8 /* ModifierFlags.Private */)) return false; // Public properties/methods are visible if its parents are visible, so: // falls through case 171 /* SyntaxKind.Constructor */: case 296 /* SyntaxKind.PropertyAssignment */: case 297 /* SyntaxKind.ShorthandPropertyAssignment */: case 205 /* SyntaxKind.ObjectLiteralExpression */: case 226 /* SyntaxKind.ClassExpression */: case 214 /* SyntaxKind.ArrowFunction */: case 213 /* SyntaxKind.FunctionExpression */: return isDefinitionVisible(checker, declaration.parent); default: return false; } } function createDefinitionFromSignatureDeclaration(typeChecker, decl, failedAliasResolution) { return createDefinitionInfo(decl, typeChecker, decl.symbol, decl, /*unverified*/ false, failedAliasResolution); } function findReferenceInPosition(refs, pos) { return ts.find(refs, function (ref) { return ts.textRangeContainsPositionInclusive(ref, pos); }); } GoToDefinition.findReferenceInPosition = findReferenceInPosition; function getDefinitionInfoForFileReference(name, targetFileName, unverified) { return { fileName: targetFileName, textSpan: ts.createTextSpanFromBounds(0, 0), kind: "script" /* ScriptElementKind.scriptElement */, name: name, containerName: undefined, containerKind: undefined, unverified: unverified, }; } /** Returns a CallLikeExpression where `node` is the target being invoked. */ function getAncestorCallLikeExpression(node) { var target = ts.findAncestor(node, function (n) { return !ts.isRightSideOfPropertyAccess(n); }); var callLike = target === null || target === void 0 ? void 0 : target.parent; return callLike && ts.isCallLikeExpression(callLike) && ts.getInvokedExpression(callLike) === target ? callLike : undefined; } 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 171 /* SyntaxKind.Constructor */: case 180 /* SyntaxKind.ConstructorType */: case 175 /* SyntaxKind.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", "link", "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, checker) { // 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 parts = []; ts.forEachUnique(declarations, function (declaration) { for (var _i = 0, _a = getCommentHavingNodes(declaration); _i < _a.length; _i++) { var jsdoc = _a[_i]; // skip comments containing @typedefs since they're not associated with particular declarations // Exceptions: // - @typedefs are themselves declarations with associated comments // - @param or @return indicate that the author thinks of it as a 'local' @typedef that's part of the function documentation if (jsdoc.comment === undefined || ts.isJSDoc(jsdoc) && declaration.kind !== 345 /* SyntaxKind.JSDocTypedefTag */ && declaration.kind !== 338 /* SyntaxKind.JSDocCallbackTag */ && jsdoc.tags && jsdoc.tags.some(function (t) { return t.kind === 345 /* SyntaxKind.JSDocTypedefTag */ || t.kind === 338 /* SyntaxKind.JSDocCallbackTag */; }) && !jsdoc.tags.some(function (t) { return t.kind === 340 /* SyntaxKind.JSDocParameterTag */ || t.kind === 341 /* SyntaxKind.JSDocReturnTag */; })) { continue; } var newparts = getDisplayPartsFromComment(jsdoc.comment, checker); if (!ts.contains(parts, newparts, isIdenticalListOfDisplayParts)) { parts.push(newparts); } } }); return ts.flatten(ts.intersperse(parts, [ts.lineBreakPart()])); } JsDoc.getJsDocCommentsFromDeclarations = getJsDocCommentsFromDeclarations; function isIdenticalListOfDisplayParts(parts1, parts2) { return ts.arraysEqual(parts1, parts2, function (p1, p2) { return p1.kind === p2.kind && p1.text === p2.text; }); } function getCommentHavingNodes(declaration) { switch (declaration.kind) { case 340 /* SyntaxKind.JSDocParameterTag */: case 347 /* SyntaxKind.JSDocPropertyTag */: return [declaration]; case 338 /* SyntaxKind.JSDocCallbackTag */: case 345 /* SyntaxKind.JSDocTypedefTag */: return [declaration, declaration.parent]; default: return ts.getJSDocCommentsAndTags(declaration); } } function getJsDocTagsFromDeclarations(declarations, checker) { // Only collect doc comments from duplicate declarations once. var infos = []; ts.forEachUnique(declarations, function (declaration) { var tags = ts.getJSDocTags(declaration); // skip comments containing @typedefs since they're not associated with particular declarations // Exceptions: // - @param or @return indicate that the author thinks of it as a 'local' @typedef that's part of the function documentation if (tags.some(function (t) { return t.kind === 345 /* SyntaxKind.JSDocTypedefTag */ || t.kind === 338 /* SyntaxKind.JSDocCallbackTag */; }) && !tags.some(function (t) { return t.kind === 340 /* SyntaxKind.JSDocParameterTag */ || t.kind === 341 /* SyntaxKind.JSDocReturnTag */; })) { return; } for (var _i = 0, tags_1 = tags; _i < tags_1.length; _i++) { var tag = tags_1[_i]; infos.push({ name: tag.tagName.text, text: getCommentDisplayParts(tag, checker) }); } }); return infos; } JsDoc.getJsDocTagsFromDeclarations = getJsDocTagsFromDeclarations; function getDisplayPartsFromComment(comment, checker) { if (typeof comment === "string") { return [ts.textPart(comment)]; } return ts.flatMap(comment, function (node) { return node.kind === 321 /* SyntaxKind.JSDocText */ ? [ts.textPart(node.text)] : ts.buildLinkParts(node, checker); }); } function getCommentDisplayParts(tag, checker) { var comment = tag.comment, kind = tag.kind; var namePart = getTagNameDisplayPart(kind); switch (kind) { case 329 /* SyntaxKind.JSDocImplementsTag */: return withNode(tag.class); case 328 /* SyntaxKind.JSDocAugmentsTag */: return withNode(tag.class); case 344 /* SyntaxKind.JSDocTemplateTag */: var templateTag = tag; var displayParts_3 = []; if (templateTag.constraint) { displayParts_3.push(ts.textPart(templateTag.constraint.getText())); } if (ts.length(templateTag.typeParameters)) { if (ts.length(displayParts_3)) { displayParts_3.push(ts.spacePart()); } var lastTypeParameter_1 = templateTag.typeParameters[templateTag.typeParameters.length - 1]; ts.forEach(templateTag.typeParameters, function (tp) { displayParts_3.push(namePart(tp.getText())); if (lastTypeParameter_1 !== tp) { displayParts_3.push.apply(displayParts_3, [ts.punctuationPart(27 /* SyntaxKind.CommaToken */), ts.spacePart()]); } }); } if (comment) { displayParts_3.push.apply(displayParts_3, __spreadArray([ts.spacePart()], getDisplayPartsFromComment(comment, checker), true)); } return displayParts_3; case 343 /* SyntaxKind.JSDocTypeTag */: return withNode(tag.typeExpression); case 345 /* SyntaxKind.JSDocTypedefTag */: case 338 /* SyntaxKind.JSDocCallbackTag */: case 347 /* SyntaxKind.JSDocPropertyTag */: case 340 /* SyntaxKind.JSDocParameterTag */: case 346 /* SyntaxKind.JSDocSeeTag */: var name = tag.name; return name ? withNode(name) : comment === undefined ? undefined : getDisplayPartsFromComment(comment, checker); default: return comment === undefined ? undefined : getDisplayPartsFromComment(comment, checker); } function withNode(node) { return addComment(node.getText()); } function addComment(s) { if (comment) { if (s.match(/^https?$/)) { return __spreadArray([ts.textPart(s)], getDisplayPartsFromComment(comment, checker), true); } else { return __spreadArray([namePart(s), ts.spacePart()], getDisplayPartsFromComment(comment, checker), true); } } else { return [ts.textPart(s)]; } } } function getTagNameDisplayPart(kind) { switch (kind) { case 340 /* SyntaxKind.JSDocParameterTag */: return ts.parameterNamePart; case 347 /* SyntaxKind.JSDocPropertyTag */: return ts.propertyNamePart; case 344 /* SyntaxKind.JSDocTemplateTag */: return ts.typeParameterNamePart; case 345 /* SyntaxKind.JSDocTypedefTag */: case 338 /* SyntaxKind.JSDocCallbackTag */: return ts.typeAliasNamePart; default: return ts.textPart; } } function getJSDocTagNameCompletions() { return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = ts.map(jsDocTagNames, function (tagName) { return { name: tagName, kind: "keyword" /* ScriptElementKind.keyword */, kindModifiers: "", sortText: ts.Completions.SortText.LocationPriority, }; })); } JsDoc.getJSDocTagNameCompletions = getJSDocTagNameCompletions; JsDoc.getJSDocTagNameCompletionDetails = getJSDocTagCompletionDetails; function getJSDocTagCompletions() { return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = ts.map(jsDocTagNames, function (tagName) { return { name: "@".concat(tagName), kind: "keyword" /* ScriptElementKind.keyword */, kindModifiers: "", sortText: ts.Completions.SortText.LocationPriority }; })); } JsDoc.getJSDocTagCompletions = getJSDocTagCompletions; function getJSDocTagCompletionDetails(name) { return { name: name, kind: "" /* ScriptElementKind.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" /* ScriptElementKind.parameterElement */, kindModifiers: "", sortText: ts.Completions.SortText.LocationPriority }; }); } JsDoc.getJSDocParameterNameCompletions = getJSDocParameterNameCompletions; function getJSDocParameterNameCompletionDetails(name) { return { name: name, kind: "parameter" /* ScriptElementKind.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, options) { 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, options); if (!commentOwnerInfo) { return undefined; } var commentOwner = commentOwnerInfo.commentOwner, parameters = commentOwnerInfo.parameters, hasReturn = commentOwnerInfo.hasReturn; var commentOwnerJSDoc = ts.hasJSDocNodes(commentOwner) && commentOwner.jsDoc ? ts.lastOrUndefined(commentOwner.jsDoc) : undefined; if (commentOwner.getStart(sourceFile) < position || commentOwnerJSDoc && commentOwnerJSDoc !== existingDocComment) { return undefined; } var indentationStr = getIndentationStringAtPosition(sourceFile, position); var isJavaScriptFile = ts.hasJSFileExtension(sourceFile.fileName); var tags = (parameters ? parameterDocComments(parameters || [], isJavaScriptFile, indentationStr, newLine) : "") + (hasReturn ? returnsDocComment(indentationStr, newLine) : ""); // 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 // * the '@returns'-tag // * 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 openComment = "/**"; var closeComment = " */"; if (tags) { var preamble = openComment + newLine + indentationStr + " * "; var endLine = tokenStart === position ? newLine + indentationStr : ""; var result = preamble + newLine + tags + indentationStr + closeComment + endLine; return { newText: result, caretOffset: preamble.length }; } return { newText: openComment + closeComment, caretOffset: 3 }; } 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 === 79 /* SyntaxKind.Identifier */ ? name.text : "param" + i; var type = isJavaScriptFile ? (dotDotDotToken ? "{...any} " : "{any} ") : ""; return "".concat(indentationStr, " * @param ").concat(type).concat(paramName).concat(newLine); }).join(""); } function returnsDocComment(indentationStr, newLine) { return "".concat(indentationStr, " * @returns").concat(newLine); } function getCommentOwnerInfo(tokenAtPos, options) { return ts.forEachAncestor(tokenAtPos, function (n) { return getCommentOwnerInfoWorker(n, options); }); } function getCommentOwnerInfoWorker(commentOwner, options) { switch (commentOwner.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 169 /* SyntaxKind.MethodDeclaration */: case 171 /* SyntaxKind.Constructor */: case 168 /* SyntaxKind.MethodSignature */: case 214 /* SyntaxKind.ArrowFunction */: var host = commentOwner; return { commentOwner: commentOwner, parameters: host.parameters, hasReturn: hasReturn(host, options) }; case 296 /* SyntaxKind.PropertyAssignment */: return getCommentOwnerInfoWorker(commentOwner.initializer, options); case 257 /* SyntaxKind.ClassDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 166 /* SyntaxKind.PropertySignature */: case 260 /* SyntaxKind.EnumDeclaration */: case 299 /* SyntaxKind.EnumMember */: case 259 /* SyntaxKind.TypeAliasDeclaration */: return { commentOwner: commentOwner }; case 237 /* SyntaxKind.VariableStatement */: { var varStatement = commentOwner; var varDeclarations = varStatement.declarationList.declarations; var host_1 = varDeclarations.length === 1 && varDeclarations[0].initializer ? getRightHandSideOfAssignment(varDeclarations[0].initializer) : undefined; return host_1 ? { commentOwner: commentOwner, parameters: host_1.parameters, hasReturn: hasReturn(host_1, options) } : { commentOwner: commentOwner }; } case 305 /* SyntaxKind.SourceFile */: return "quit"; case 261 /* SyntaxKind.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 === 261 /* SyntaxKind.ModuleDeclaration */ ? undefined : { commentOwner: commentOwner }; case 238 /* SyntaxKind.ExpressionStatement */: return getCommentOwnerInfoWorker(commentOwner.expression, options); case 221 /* SyntaxKind.BinaryExpression */: { var be = commentOwner; if (ts.getAssignmentDeclarationKind(be) === 0 /* AssignmentDeclarationKind.None */) { return "quit"; } return ts.isFunctionLike(be.right) ? { commentOwner: commentOwner, parameters: be.right.parameters, hasReturn: hasReturn(be.right, options) } : { commentOwner: commentOwner }; } case 167 /* SyntaxKind.PropertyDeclaration */: var init = commentOwner.initializer; if (init && (ts.isFunctionExpression(init) || ts.isArrowFunction(init))) { return { commentOwner: commentOwner, parameters: init.parameters, hasReturn: hasReturn(init, options) }; } } } function hasReturn(node, options) { return !!(options === null || options === void 0 ? void 0 : options.generateReturnInDocTemplate) && (ts.isArrowFunction(node) && ts.isExpression(node.body) || ts.isFunctionLikeDeclaration(node) && node.body && ts.isBlock(node.body) && !!ts.forEachReturnStatement(node.body, function (n) { return n; })); } function getRightHandSideOfAssignment(rightHandSide) { while (rightHandSide.kind === 212 /* SyntaxKind.ParenthesizedExpression */) { rightHandSide = rightHandSide.expression; } switch (rightHandSide.kind) { case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: return rightHandSide; case 226 /* SyntaxKind.ClassExpression */: return ts.find(rightHandSide.members, ts.isConstructorDeclaration); } } })(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_7 = 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_7(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 267 /* SyntaxKind.ImportClause */: case 270 /* SyntaxKind.ImportSpecifier */: case 265 /* SyntaxKind.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 === 162 /* SyntaxKind.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 === 162 /* SyntaxKind.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) : "" /* ScriptElementKind.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 = new ts.Map(); } 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); trackedEs5Classes = undefined; 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(); } function addNodeWithRecursiveInitializer(node) { if (node.initializer && isFunctionOrClassExpression(node.initializer)) { startNode(node); ts.forEachChild(node.initializer, addChildrenRecursively); endNode(); } else { addNodeWithRecursiveChild(node, node.initializer); } } /** * Historically, we've elided dynamic names from the nav tree (including late bound names), * but included certain "well known" symbol names. While we no longer distinguish those well-known * symbols from other unique symbols, we do the below to retain those members in the nav tree. */ function hasNavigationBarName(node) { return !ts.hasDynamicName(node) || (node.kind !== 221 /* SyntaxKind.BinaryExpression */ && ts.isPropertyAccessExpression(node.name.expression) && ts.isIdentifier(node.name.expression.expression) && ts.idText(node.name.expression.expression) === "Symbol"); } /** 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 171 /* SyntaxKind.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 169 /* SyntaxKind.MethodDeclaration */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: case 168 /* SyntaxKind.MethodSignature */: if (hasNavigationBarName(node)) { addNodeWithRecursiveChild(node, node.body); } break; case 167 /* SyntaxKind.PropertyDeclaration */: if (hasNavigationBarName(node)) { addNodeWithRecursiveInitializer(node); } break; case 166 /* SyntaxKind.PropertySignature */: if (hasNavigationBarName(node)) { addLeafNode(node); } break; case 267 /* SyntaxKind.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 === 268 /* SyntaxKind.NamespaceImport */) { addLeafNode(namedBindings); } else { for (var _c = 0, _d = namedBindings.elements; _c < _d.length; _c++) { var element = _d[_c]; addLeafNode(element); } } } break; case 297 /* SyntaxKind.ShorthandPropertyAssignment */: addNodeWithRecursiveChild(node, node.name); break; case 298 /* SyntaxKind.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 203 /* SyntaxKind.BindingElement */: case 296 /* SyntaxKind.PropertyAssignment */: case 254 /* SyntaxKind.VariableDeclaration */: { var child = node; if (ts.isBindingPattern(child.name)) { addChildrenRecursively(child.name); } else { addNodeWithRecursiveInitializer(child); } break; } case 256 /* SyntaxKind.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 214 /* SyntaxKind.ArrowFunction */: case 213 /* SyntaxKind.FunctionExpression */: addNodeWithRecursiveChild(node, node.body); break; case 260 /* SyntaxKind.EnumDeclaration */: startNode(node); for (var _e = 0, _f = node.members; _e < _f.length; _e++) { var member = _f[_e]; if (!isComputedProperty(member)) { addLeafNode(member); } } endNode(); break; case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 258 /* SyntaxKind.InterfaceDeclaration */: startNode(node); for (var _g = 0, _h = node.members; _g < _h.length; _g++) { var member = _h[_g]; addChildrenRecursively(member); } endNode(); break; case 261 /* SyntaxKind.ModuleDeclaration */: addNodeWithRecursiveChild(node, getInteriorModule(node).body); break; case 271 /* SyntaxKind.ExportAssignment */: { var expression_1 = node.expression; var child = ts.isObjectLiteralExpression(expression_1) || ts.isCallExpression(expression_1) ? expression_1 : ts.isArrowFunction(expression_1) || ts.isFunctionExpression(expression_1) ? expression_1.body : undefined; if (child) { startNode(node); addChildrenRecursively(child); endNode(); } else { addLeafNode(node); } break; } case 275 /* SyntaxKind.ExportSpecifier */: case 265 /* SyntaxKind.ImportEqualsDeclaration */: case 176 /* SyntaxKind.IndexSignature */: case 174 /* SyntaxKind.CallSignature */: case 175 /* SyntaxKind.ConstructSignature */: case 259 /* SyntaxKind.TypeAliasDeclaration */: addLeafNode(node); break; case 208 /* SyntaxKind.CallExpression */: case 221 /* SyntaxKind.BinaryExpression */: { var special = ts.getAssignmentDeclarationKind(node); switch (special) { case 1 /* AssignmentDeclarationKind.ExportsProperty */: case 2 /* AssignmentDeclarationKind.ModuleExports */: addNodeWithRecursiveChild(node, node.right); return; case 6 /* AssignmentDeclarationKind.Prototype */: case 3 /* AssignmentDeclarationKind.PrototypeProperty */: { var binaryExpression = node; var assignmentTarget = binaryExpression.left; var prototypeAccess = special === 3 /* AssignmentDeclarationKind.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 /* AssignmentDeclarationKind.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 /* AssignmentDeclarationKind.ObjectDefinePropertyValue */: case 9 /* AssignmentDeclarationKind.ObjectDefinePrototypeProperty */: { var defineCall = node; var className = special === 7 /* AssignmentDeclarationKind.ObjectDefinePropertyValue */ ? defineCall.arguments[0] : defineCall.arguments[0].expression; var memberName = defineCall.arguments[1]; var _j = startNestedNodes(node, className), depth = _j[0], classNameIdentifier = _j[1]; startNode(node, classNameIdentifier); startNode(node, ts.setTextRange(ts.factory.createIdentifier(memberName.text), memberName)); addChildrenRecursively(node.arguments[2]); endNode(); endNode(); endNestedNodes(depth); return; } case 5 /* AssignmentDeclarationKind.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 /* AssignmentDeclarationKind.ThisProperty */: case 0 /* AssignmentDeclarationKind.None */: case 8 /* AssignmentDeclarationKind.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 = new ts.Map(); 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 /* AssignmentDeclarationKind.Property */] = true, _a[3 /* AssignmentDeclarationKind.PrototypeProperty */] = true, _a[7 /* AssignmentDeclarationKind.ObjectDefinePropertyValue */] = true, _a[9 /* AssignmentDeclarationKind.ObjectDefinePrototypeProperty */] = true, _a[0 /* AssignmentDeclarationKind.None */] = false, _a[1 /* AssignmentDeclarationKind.ExportsProperty */] = false, _a[2 /* AssignmentDeclarationKind.ModuleExports */] = false, _a[8 /* AssignmentDeclarationKind.ObjectDefinePropertyExports */] = false, _a[6 /* AssignmentDeclarationKind.Prototype */] = true, _a[4 /* AssignmentDeclarationKind.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 /* AssignmentDeclarationKind.None */; var aAssignmentDeclarationKind = ts.isBinaryExpression(a.node) || ts.isCallExpression(a.node) ? ts.getAssignmentDeclarationKind(a.node) : 0 /* AssignmentDeclarationKind.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) && isSynthesized(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // class (generated) & member || (ts.isClassDeclaration(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & class (generated) || (ts.isClassDeclaration(a.node) && isSynthesized(a.node) && isPossibleConstructor(b.node)) // class (generated) & ctor || (ts.isClassDeclaration(b.node) && isPossibleConstructor(a.node) && isSynthesized(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.factory.createConstructorDeclaration(/* 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 || [__assign({}, a)], [ctor]); } else { if (a.children || b.children) { a.children = ts.concatenate(a.children || [__assign({}, a)], b.children || [b]); if (a.children) { mergeChildren(a.children, a); sortChildren(a.children); } } } lastANode = a.node = ts.setTextRange(ts.factory.createClassDeclaration( /* decorators */ undefined, /* modifiers */ undefined, a.name || ts.factory.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.factory.createClassDeclaration( /* decorators */ undefined, /* modifiers */ undefined, a.name || ts.factory.createIdentifier("__class__"), /* typeParameters */ undefined, /* heritageClauses */ undefined, []), b.node)); } return true; } return bAssignmentDeclarationKind === 0 /* AssignmentDeclarationKind.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 167 /* SyntaxKind.PropertyDeclaration */: case 169 /* SyntaxKind.MethodDeclaration */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: return ts.isStatic(a) === ts.isStatic(b); case 261 /* SyntaxKind.ModuleDeclaration */: return areSameModule(a, b) && getFullyQualifiedModuleName(a) === getFullyQualifiedModuleName(b); default: return true; } } function isSynthesized(node) { return !!(node.flags & 8 /* NodeFlags.Synthesized */); } // 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) { if (!a.body || !b.body) { return a.body === b.body; } return a.body.kind === b.body.kind && (a.body.kind !== 261 /* SyntaxKind.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 === 261 /* SyntaxKind.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 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: case 226 /* SyntaxKind.ClassExpression */: return getFunctionOrClassName(node); default: return undefined; } } function getItemName(node, name) { if (node.kind === 261 /* SyntaxKind.ModuleDeclaration */) { return cleanText(getModuleName(node)); } if (name) { var text = ts.isIdentifier(name) ? name.text : ts.isElementAccessExpression(name) ? "[".concat(nodeText(name.argumentExpression), "]") : nodeText(name); if (text.length > 0) { return cleanText(text); } } switch (node.kind) { case 305 /* SyntaxKind.SourceFile */: var sourceFile = node; return ts.isExternalModule(sourceFile) ? "\"".concat(ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))), "\"") : ""; case 271 /* SyntaxKind.ExportAssignment */: return ts.isExportAssignment(node) && node.isExportEquals ? "export=" /* InternalSymbolName.ExportEquals */ : "default" /* InternalSymbolName.Default */; case 214 /* SyntaxKind.ArrowFunction */: case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: if (ts.getSyntacticModifierFlags(node) & 512 /* ModifierFlags.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 readability in the // navigation bar. return getFunctionOrClassName(node); case 171 /* SyntaxKind.Constructor */: return "constructor"; case 175 /* SyntaxKind.ConstructSignature */: return "new()"; case 174 /* SyntaxKind.CallSignature */: return "()"; case 176 /* SyntaxKind.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 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 260 /* SyntaxKind.EnumDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: case 305 /* SyntaxKind.SourceFile */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 345 /* SyntaxKind.JSDocTypedefTag */: case 338 /* SyntaxKind.JSDocCallbackTag */: return true; case 214 /* SyntaxKind.ArrowFunction */: case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: return isTopLevelFunctionDeclaration(item); default: return false; } function isTopLevelFunctionDeclaration(item) { if (!item.node.body) { return false; } switch (navigationBarNodeKind(item.parent)) { case 262 /* SyntaxKind.ModuleBlock */: case 305 /* SyntaxKind.SourceFile */: case 169 /* SyntaxKind.MethodDeclaration */: case 171 /* SyntaxKind.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); } return getFullyQualifiedModuleName(moduleDeclaration); } function getFullyQualifiedModuleName(moduleDeclaration) { // Otherwise, we need to aggregate each identifier to build up the qualified name. var result = [ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name)]; while (moduleDeclaration.body && moduleDeclaration.body.kind === 261 /* SyntaxKind.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 === 162 /* SyntaxKind.ComputedPropertyName */; } function getNodeSpan(node) { return node.kind === 305 /* SyntaxKind.SourceFile */ ? ts.createTextSpanFromRange(node) : ts.createTextSpanFromNode(node, curSourceFile); } function getModifiers(node) { if (node.parent && node.parent.kind === 254 /* SyntaxKind.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 === 63 /* SyntaxKind.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.getSyntacticModifierFlags(node) & 512 /* ModifierFlags.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 "".concat(name, " callback"); } var args = cleanText(ts.mapDefined(parent.arguments, function (a) { return ts.isStringLiteralLike(a) ? a.getText(curSourceFile) : undefined; }).join(", ")); return "".concat(name, "(").concat(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 : "".concat(left, ".").concat(right); } else { return undefined; } } function isFunctionOrClassExpression(node) { switch (node.kind) { case 214 /* SyntaxKind.ArrowFunction */: case 213 /* SyntaxKind.FunctionExpression */: case 226 /* SyntaxKind.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, skipDestructiveCodeActions) { var changeTracker = ts.textChanges.ChangeTracker.fromContext({ host: host, formatContext: formatContext, preferences: preferences }); var coalesceAndOrganizeImports = function (importGroup) { return ts.stableSort(coalesceImports(removeUnusedImports(importGroup, sourceFile, program, skipDestructiveCodeActions)), function (s1, s2) { return compareImportsOrRequireStatements(s1, s2); }); }; // All of the old ImportDeclarations in the file, in syntactic order. var topLevelImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, sourceFile.statements.filter(ts.isImportDeclaration)); topLevelImportGroupDecls.forEach(function (importGroupDecl) { return organizeImportsWorker(importGroupDecl, 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 ambientModuleImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, ambientModule.body.statements.filter(ts.isImportDeclaration)); ambientModuleImportGroupDecls.forEach(function (importGroupDecl) { return organizeImportsWorker(importGroupDecl, 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 all nodes if there are no imports. if (newImportDecls.length === 0) { // Consider the first node to have trailingTrivia as we want to exclude the // "header" comment. changeTracker.deleteNodes(sourceFile, oldImportDecls, { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, }, /*hasTrailingComment*/ true); } else { // Note: Delete the surrounding trivia because it will have been retained in newImportDecls. var replaceOptions = { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options), }; changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, replaceOptions); var hasTrailingComment = changeTracker.nodeHasTrailingComment(sourceFile, oldImportDecls[0], replaceOptions); changeTracker.deleteNodes(sourceFile, oldImportDecls.slice(1), { trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, }, hasTrailingComment); } } } OrganizeImports.organizeImports = organizeImports; function groupImportsByNewlineContiguous(sourceFile, importDecls) { var scanner = ts.createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, sourceFile.languageVariant); var groupImports = []; var groupIndex = 0; for (var _i = 0, importDecls_1 = importDecls; _i < importDecls_1.length; _i++) { var topLevelImportDecl = importDecls_1[_i]; if (isNewGroup(sourceFile, topLevelImportDecl, scanner)) { groupIndex++; } if (!groupImports[groupIndex]) { groupImports[groupIndex] = []; } groupImports[groupIndex].push(topLevelImportDecl); } return groupImports; } // a new group is created if an import includes at least two new line // new line from multi-line comment doesn't count function isNewGroup(sourceFile, topLevelImportDecl, scanner) { var startPos = topLevelImportDecl.getFullStart(); var endPos = topLevelImportDecl.getStart(); scanner.setText(sourceFile.text, startPos, endPos - startPos); var numberOfNewLines = 0; while (scanner.getTokenPos() < endPos) { var tokenKind = scanner.scan(); if (tokenKind === 4 /* SyntaxKind.NewLineTrivia */) { numberOfNewLines++; if (numberOfNewLines >= 2) { return true; } } } return false; } function removeUnusedImports(oldImports, sourceFile, program, skipDestructiveCodeActions) { // As a precaution, consider unused import detection to be destructive (GH #43051) if (skipDestructiveCodeActions) { return oldImports; } var typeChecker = program.getTypeChecker(); var compilerOptions = program.getCompilerOptions(); var jsxNamespace = typeChecker.getJsxNamespace(sourceFile); var jsxFragmentFactory = typeChecker.getJsxFragmentFactory(sourceFile); var jsxElementsPresent = !!(sourceFile.transformFlags & 2 /* TransformFlags.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.factory.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.factory.createImportDeclaration(importDecl.decorators, importDecl.modifiers, /*importClause*/ undefined, moduleSpecifier, /*assertClause*/ undefined)); } // 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 || jsxFragmentFactory && identifier.text === jsxFragmentFactory) && ts.jsxModeNeedsExplicitImport(compilerOptions.jsx) || 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.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("default"), defaultImport.importClause.name)); // TODO: GH#18217 } } newImportSpecifiers.push.apply(newImportSpecifiers, getNewImportSpecifiers(namedImports)); var sortedImportSpecifiers = sortSpecifiers(newImportSpecifiers); var importDecl = defaultImports.length > 0 ? defaultImports[0] : namedImports[0]; var newNamedImports = sortedImportSpecifiers.length === 0 ? newDefaultImport ? undefined : ts.factory.createNamedImports(ts.emptyArray) : namedImports.length === 0 ? ts.factory.createNamedImports(sortedImportSpecifiers) : ts.factory.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.factory.updateExportDeclaration(exportDecl, exportDecl.decorators, exportDecl.modifiers, exportDecl.isTypeOnly, exportDecl.exportClause && (ts.isNamedExports(exportDecl.exportClause) ? ts.factory.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) : ts.factory.updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name)), exportDecl.moduleSpecifier, exportDecl.assertClause)); } 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.factory.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.factory.updateImportClause(importDeclaration.importClause, importDeclaration.importClause.isTypeOnly, name, namedBindings), // TODO: GH#18217 importDeclaration.moduleSpecifier, importDeclaration.assertClause); } function sortSpecifiers(specifiers) { return ts.stableSort(specifiers, compareImportOrExportSpecifiers); } function compareImportOrExportSpecifiers(s1, s2) { return ts.compareBooleans(s1.isTypeOnly, s2.isTypeOnly) || compareIdentifiers(s1.propertyName || s1.name, s2.propertyName || s2.name) || compareIdentifiers(s1.name, s2.name); } OrganizeImports.compareImportOrExportSpecifiers = compareImportOrExportSpecifiers; /* internal */ // Exported for testing function compareModuleSpecifiers(m1, m2) { var name1 = m1 === undefined ? undefined : getExternalModuleName(m1); var name2 = m2 === undefined ? undefined : 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); } function getModuleSpecifierExpression(declaration) { var _a; switch (declaration.kind) { case 265 /* SyntaxKind.ImportEqualsDeclaration */: return (_a = ts.tryCast(declaration.moduleReference, ts.isExternalModuleReference)) === null || _a === void 0 ? void 0 : _a.expression; case 266 /* SyntaxKind.ImportDeclaration */: return declaration.moduleSpecifier; case 237 /* SyntaxKind.VariableStatement */: return declaration.declarationList.declarations[0].initializer.arguments[0]; } } function importsAreSorted(imports) { return ts.arrayIsSorted(imports, compareImportsOrRequireStatements); } OrganizeImports.importsAreSorted = importsAreSorted; function importSpecifiersAreSorted(imports) { return ts.arrayIsSorted(imports, compareImportOrExportSpecifiers); } OrganizeImports.importSpecifiersAreSorted = importSpecifiersAreSorted; function getImportDeclarationInsertionIndex(sortedImports, newImport) { var index = ts.binarySearch(sortedImports, newImport, ts.identity, compareImportsOrRequireStatements); return index < 0 ? ~index : index; } OrganizeImports.getImportDeclarationInsertionIndex = getImportDeclarationInsertionIndex; function getImportSpecifierInsertionIndex(sortedImports, newImport) { var index = ts.binarySearch(sortedImports, newImport, ts.identity, compareImportOrExportSpecifiers); return index < 0 ? ~index : index; } OrganizeImports.getImportSpecifierInsertionIndex = getImportSpecifierInsertionIndex; function compareImportsOrRequireStatements(s1, s2) { return compareModuleSpecifiers(getModuleSpecifierExpression(s1), getModuleSpecifierExpression(s2)) || compareImportKind(s1, s2); } OrganizeImports.compareImportsOrRequireStatements = compareImportsOrRequireStatements; function compareImportKind(s1, s2) { return ts.compareValues(getImportKindOrder(s1), getImportKindOrder(s2)); } // 1. Side-effect imports // 2. Type-only imports // 3. Namespace imports // 4. Default imports // 5. Named imports // 6. ImportEqualsDeclarations // 7. Require variable statements function getImportKindOrder(s1) { var _a; switch (s1.kind) { case 266 /* SyntaxKind.ImportDeclaration */: if (!s1.importClause) return 0; if (s1.importClause.isTypeOnly) return 1; if (((_a = s1.importClause.namedBindings) === null || _a === void 0 ? void 0 : _a.kind) === 268 /* SyntaxKind.NamespaceImport */) return 2; if (s1.importClause.name) return 3; return 4; case 265 /* SyntaxKind.ImportEqualsDeclaration */: return 5; case 237 /* SyntaxKind.VariableStatement */: return 6; } } function getNewImportSpecifiers(namedImports) { return ts.flatMap(namedImports, function (namedImport) { return ts.map(tryGetNamedBindingElements(namedImport), function (importSpecifier) { return importSpecifier.name && importSpecifier.propertyName && importSpecifier.name.escapedText === importSpecifier.propertyName.escapedText ? ts.factory.updateImportSpecifier(importSpecifier, importSpecifier.isTypeOnly, /*propertyName*/ undefined, importSpecifier.name) : importSpecifier; }); }); } function tryGetNamedBindingElements(namedImport) { var _a; return ((_a = namedImport.importClause) === null || _a === void 0 ? void 0 : _a.namedBindings) && ts.isNamedImports(namedImport.importClause.namedBindings) ? namedImport.importClause.namedBindings.elements : undefined; } })(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 = __spreadArray(__spreadArray([], sourceFile.statements, true), [sourceFile.endOfFileToken], false); 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], 100 /* SyntaxKind.ImportKeyword */, sourceFile).getStart(sourceFile), statements[lastImport].getEnd(), "imports" /* OutliningSpanKind.Imports */)); } } function visitNonImportNode(n) { var _a; if (depthRemaining === 0) return; cancellationToken.throwIfCancellationRequested(); if (ts.isDeclaration(n) || ts.isVariableStatement(n) || ts.isReturnStatement(n) || ts.isCallOrNewExpression(n) || n.kind === 1 /* SyntaxKind.EndOfFileToken */) { addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out); } if (ts.isFunctionLike(n) && ts.isBinaryExpression(n.parent) && ts.isPropertyAccessExpression(n.parent.left)) { addOutliningForLeadingCommentsForNode(n.parent.left, sourceFile, cancellationToken, out); } if (ts.isBlock(n) || ts.isModuleBlock(n)) { addOutliningForLeadingCommentsForPos(n.statements.end, sourceFile, cancellationToken, out); } if (ts.isClassLike(n) || ts.isInterfaceDeclaration(n)) { addOutliningForLeadingCommentsForPos(n.members.end, 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 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" /* OutliningSpanKind.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 = /^#(end)?region(?:\s+(.*))?(?:\r)?$/; function isRegionDelimiter(lineText) { // We trim the leading whitespace and // without the regex since the // multiple potential whitespace matches can make for some gnarly backtracking behavior lineText = ts.trimStringStart(lineText); if (!ts.startsWith(lineText, "\/\/")) { return null; // eslint-disable-line no-null/no-null } lineText = ts.trimString(lineText.slice(2)); return regionDelimiterRegExp.exec(lineText); } function addOutliningForLeadingCommentsForPos(pos, sourceFile, cancellationToken, out) { var comments = ts.getLeadingCommentRanges(sourceFile.text, pos); 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_1 = _a.pos, end = _a.end; cancellationToken.throwIfCancellationRequested(); switch (kind) { case 2 /* SyntaxKind.SingleLineCommentTrivia */: // never fold region delimiters into single-line comment regions var commentText = sourceText.slice(pos_1, 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_1; } lastSingleLineCommentEnd = end; singleLineCommentCount++; break; case 3 /* SyntaxKind.MultiLineCommentTrivia */: combineAndAddMultipleSingleLineComments(); out.push(createOutliningSpanFromBounds(pos_1, end, "comment" /* OutliningSpanKind.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" /* OutliningSpanKind.Comment */)); } } } function addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out) { if (ts.isJsxText(n)) return; addOutliningForLeadingCommentsForPos(n.pos, sourceFile, cancellationToken, out); } function createOutliningSpanFromBounds(pos, end, kind) { return createOutliningSpan(ts.createTextSpanFromBounds(pos, end), kind); } function getOutliningSpanForNode(n, sourceFile) { switch (n.kind) { case 235 /* SyntaxKind.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 240 /* SyntaxKind.DoStatement */: case 243 /* SyntaxKind.ForInStatement */: case 244 /* SyntaxKind.ForOfStatement */: case 242 /* SyntaxKind.ForStatement */: case 239 /* SyntaxKind.IfStatement */: case 241 /* SyntaxKind.WhileStatement */: case 248 /* SyntaxKind.WithStatement */: case 292 /* SyntaxKind.CatchClause */: return spanForNode(n.parent); case 252 /* SyntaxKind.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, 96 /* SyntaxKind.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" /* OutliningSpanKind.Code */); } case 262 /* SyntaxKind.ModuleBlock */: return spanForNode(n.parent); case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 263 /* SyntaxKind.CaseBlock */: case 182 /* SyntaxKind.TypeLiteral */: case 201 /* SyntaxKind.ObjectBindingPattern */: return spanForNode(n); case 184 /* SyntaxKind.TupleType */: return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !ts.isTupleTypeNode(n.parent), 22 /* SyntaxKind.OpenBracketToken */); case 289 /* SyntaxKind.CaseClause */: case 290 /* SyntaxKind.DefaultClause */: return spanForNodeArray(n.statements); case 205 /* SyntaxKind.ObjectLiteralExpression */: return spanForObjectOrArrayLiteral(n); case 204 /* SyntaxKind.ArrayLiteralExpression */: return spanForObjectOrArrayLiteral(n, 22 /* SyntaxKind.OpenBracketToken */); case 278 /* SyntaxKind.JsxElement */: return spanForJSXElement(n); case 282 /* SyntaxKind.JsxFragment */: return spanForJSXFragment(n); case 279 /* SyntaxKind.JsxSelfClosingElement */: case 280 /* SyntaxKind.JsxOpeningElement */: return spanForJSXAttributes(n.attributes); case 223 /* SyntaxKind.TemplateExpression */: case 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */: return spanForTemplateLiteral(n); case 202 /* SyntaxKind.ArrayBindingPattern */: return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !ts.isBindingElement(n.parent), 22 /* SyntaxKind.OpenBracketToken */); case 214 /* SyntaxKind.ArrowFunction */: return spanForArrowFunction(n); case 208 /* SyntaxKind.CallExpression */: return spanForCallExpression(n); case 212 /* SyntaxKind.ParenthesizedExpression */: return spanForParenthesizedExpression(n); } function spanForCallExpression(node) { if (!node.arguments.length) { return undefined; } var openToken = ts.findChildOfKind(node, 20 /* SyntaxKind.OpenParenToken */, sourceFile); var closeToken = ts.findChildOfKind(node, 21 /* SyntaxKind.CloseParenToken */, sourceFile); if (!openToken || !closeToken || ts.positionsAreOnSameLine(openToken.pos, closeToken.pos, sourceFile)) { return undefined; } return spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ false, /*useFullStart*/ true); } function spanForArrowFunction(node) { if (ts.isBlock(node.body) || ts.isParenthesizedExpression(node.body) || ts.positionsAreOnSameLine(node.body.getFullStart(), node.body.getEnd(), sourceFile)) { return undefined; } var textSpan = ts.createTextSpanFromBounds(node.body.getFullStart(), node.body.getEnd()); return createOutliningSpan(textSpan, "code" /* OutliningSpanKind.Code */, ts.createTextSpanFromNode(node)); } function spanForJSXElement(node) { var textSpan = ts.createTextSpanFromBounds(node.openingElement.getStart(sourceFile), node.closingElement.getEnd()); var tagName = node.openingElement.tagName.getText(sourceFile); var bannerText = "<" + tagName + ">..."; return createOutliningSpan(textSpan, "code" /* OutliningSpanKind.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" /* OutliningSpanKind.Code */, textSpan, /*autoCollapse*/ false, bannerText); } function spanForJSXAttributes(node) { if (node.properties.length === 0) { return undefined; } return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), "code" /* OutliningSpanKind.Code */); } function spanForTemplateLiteral(node) { if (node.kind === 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */ && node.text.length === 0) { return undefined; } return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), "code" /* OutliningSpanKind.Code */); } function spanForObjectOrArrayLiteral(node, open) { if (open === void 0) { open = 18 /* SyntaxKind.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 /* SyntaxKind.OpenBraceToken */; } if (close === void 0) { close = open === 18 /* SyntaxKind.OpenBraceToken */ ? 19 /* SyntaxKind.CloseBraceToken */ : 23 /* SyntaxKind.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" /* OutliningSpanKind.Code */) : undefined; } function spanForParenthesizedExpression(node) { if (ts.positionsAreOnSameLine(node.getStart(), node.getEnd(), sourceFile)) return undefined; var textSpan = ts.createTextSpanFromBounds(node.getStart(), node.getEnd()); return createOutliningSpan(textSpan, "code" /* OutliningSpanKind.Code */, ts.createTextSpanFromNode(node)); } } function functionSpan(node, body, sourceFile) { var openToken = tryGetFunctionOpenToken(node, body, sourceFile); var closeToken = ts.findChildOfKind(body, 19 /* SyntaxKind.CloseBraceToken */, sourceFile); return openToken && closeToken && spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ node.kind !== 214 /* SyntaxKind.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" /* OutliningSpanKind.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 }; } function tryGetFunctionOpenToken(node, body, sourceFile) { if (ts.isNodeArrayMultiLine(node.parameters, sourceFile)) { var openParenToken = ts.findChildOfKind(node, 20 /* SyntaxKind.OpenParenToken */, sourceFile); if (openParenToken) { return openParenToken; } } return ts.findChildOfKind(body, 18 /* SyntaxKind.OpenBraceToken */, sourceFile); } })(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 = new ts.Map(); 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 /* CharacterCodes.space */ && ch !== 42 /* CharacterCodes.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 /* Comparison.GreaterThan */ : b === undefined ? -1 /* Comparison.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 /* CharacterCodes.A */ && ch <= 90 /* CharacterCodes.Z */) { return true; } if (ch < 127 /* CharacterCodes.maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 99 /* ScriptTarget.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 /* CharacterCodes.a */ && ch <= 122 /* CharacterCodes.z */) { return true; } if (ch < 127 /* CharacterCodes.maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 99 /* ScriptTarget.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_8 = 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_3 = _loop_8(start); if (typeof state_3 === "object") return state_3.value; } return -1; } function toLowerCase(ch) { // Fast convert for the ascii range. if (ch >= 65 /* CharacterCodes.A */ && ch <= 90 /* CharacterCodes.Z */) { return 97 /* CharacterCodes.a */ + (ch - 65 /* CharacterCodes.A */); } if (ch < 127 /* CharacterCodes.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 /* CharacterCodes._0 */ && ch <= 57 /* CharacterCodes._9 */; } function isWordChar(ch) { return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* CharacterCodes._ */ || ch === 36 /* CharacterCodes.$ */; } 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 /* CharacterCodes.exclamation */: case 34 /* CharacterCodes.doubleQuote */: case 35 /* CharacterCodes.hash */: case 37 /* CharacterCodes.percent */: case 38 /* CharacterCodes.ampersand */: case 39 /* CharacterCodes.singleQuote */: case 40 /* CharacterCodes.openParen */: case 41 /* CharacterCodes.closeParen */: case 42 /* CharacterCodes.asterisk */: case 44 /* CharacterCodes.comma */: case 45 /* CharacterCodes.minus */: case 46 /* CharacterCodes.dot */: case 47 /* CharacterCodes.slash */: case 58 /* CharacterCodes.colon */: case 59 /* CharacterCodes.semicolon */: case 63 /* CharacterCodes.question */: case 64 /* CharacterCodes.at */: case 91 /* CharacterCodes.openBracket */: case 92 /* CharacterCodes.backslash */: case 93 /* CharacterCodes.closeBracket */: case 95 /* CharacterCodes._ */: case 123 /* CharacterCodes.openBrace */: case 125 /* CharacterCodes.closeBrace */: return true; } return false; } function isAllPunctuation(identifier, start, end) { return every(identifier, function (ch) { return charIsPunctuation(ch) && ch !== 95 /* CharacterCodes._ */; }, 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 /* ScriptTarget.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 /* SyntaxKind.OpenBraceToken */) { braceNesting++; } else if (currentToken === 19 /* SyntaxKind.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 === 135 /* SyntaxKind.DeclareKeyword */) { // declare module "mod" token = nextToken(); if (token === 141 /* SyntaxKind.ModuleKeyword */) { token = nextToken(); if (token === 10 /* SyntaxKind.StringLiteral */) { recordAmbientExternalModule(); } } return true; } return false; } /** * Returns true if at least one token was consumed from the stream */ function tryConsumeImport() { if (lastToken === 24 /* SyntaxKind.DotToken */) { return false; } var token = ts.scanner.getToken(); if (token === 100 /* SyntaxKind.ImportKeyword */) { token = nextToken(); if (token === 20 /* SyntaxKind.OpenParenToken */) { token = nextToken(); if (token === 10 /* SyntaxKind.StringLiteral */ || token === 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */) { // import("mod"); recordModuleName(); return true; } } else if (token === 10 /* SyntaxKind.StringLiteral */) { // import "mod"; recordModuleName(); return true; } else { if (token === 152 /* SyntaxKind.TypeKeyword */) { var skipTypeKeyword = ts.scanner.lookAhead(function () { var token = ts.scanner.scan(); return token !== 156 /* SyntaxKind.FromKeyword */ && (token === 41 /* SyntaxKind.AsteriskToken */ || token === 18 /* SyntaxKind.OpenBraceToken */ || token === 79 /* SyntaxKind.Identifier */ || ts.isKeyword(token)); }); if (skipTypeKeyword) { token = nextToken(); } } if (token === 79 /* SyntaxKind.Identifier */ || ts.isKeyword(token)) { token = nextToken(); if (token === 156 /* SyntaxKind.FromKeyword */) { token = nextToken(); if (token === 10 /* SyntaxKind.StringLiteral */) { // import d from "mod"; recordModuleName(); return true; } } else if (token === 63 /* SyntaxKind.EqualsToken */) { if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } else if (token === 27 /* SyntaxKind.CommaToken */) { // consume comma and keep going token = nextToken(); } else { // unknown syntax return true; } } if (token === 18 /* SyntaxKind.OpenBraceToken */) { token = nextToken(); // consume "{ a as B, c, d as D}" clauses // make sure that it stops on EOF while (token !== 19 /* SyntaxKind.CloseBraceToken */ && token !== 1 /* SyntaxKind.EndOfFileToken */) { token = nextToken(); } if (token === 19 /* SyntaxKind.CloseBraceToken */) { token = nextToken(); if (token === 156 /* SyntaxKind.FromKeyword */) { token = nextToken(); if (token === 10 /* SyntaxKind.StringLiteral */) { // import {a as A} from "mod"; // import d, {a, b as B} from "mod" recordModuleName(); } } } } else if (token === 41 /* SyntaxKind.AsteriskToken */) { token = nextToken(); if (token === 127 /* SyntaxKind.AsKeyword */) { token = nextToken(); if (token === 79 /* SyntaxKind.Identifier */ || ts.isKeyword(token)) { token = nextToken(); if (token === 156 /* SyntaxKind.FromKeyword */) { token = nextToken(); if (token === 10 /* SyntaxKind.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 === 93 /* SyntaxKind.ExportKeyword */) { markAsExternalModuleIfTopLevel(); token = nextToken(); if (token === 152 /* SyntaxKind.TypeKeyword */) { var skipTypeKeyword = ts.scanner.lookAhead(function () { var token = ts.scanner.scan(); return token === 41 /* SyntaxKind.AsteriskToken */ || token === 18 /* SyntaxKind.OpenBraceToken */; }); if (skipTypeKeyword) { token = nextToken(); } } if (token === 18 /* SyntaxKind.OpenBraceToken */) { token = nextToken(); // consume "{ a as B, c, d as D}" clauses // make sure it stops on EOF while (token !== 19 /* SyntaxKind.CloseBraceToken */ && token !== 1 /* SyntaxKind.EndOfFileToken */) { token = nextToken(); } if (token === 19 /* SyntaxKind.CloseBraceToken */) { token = nextToken(); if (token === 156 /* SyntaxKind.FromKeyword */) { token = nextToken(); if (token === 10 /* SyntaxKind.StringLiteral */) { // export {a as A} from "mod"; // export {a, b as B} from "mod" recordModuleName(); } } } } else if (token === 41 /* SyntaxKind.AsteriskToken */) { token = nextToken(); if (token === 156 /* SyntaxKind.FromKeyword */) { token = nextToken(); if (token === 10 /* SyntaxKind.StringLiteral */) { // export * from "mod" recordModuleName(); } } } else if (token === 100 /* SyntaxKind.ImportKeyword */) { token = nextToken(); if (token === 152 /* SyntaxKind.TypeKeyword */) { var skipTypeKeyword = ts.scanner.lookAhead(function () { var token = ts.scanner.scan(); return token === 79 /* SyntaxKind.Identifier */ || ts.isKeyword(token); }); if (skipTypeKeyword) { token = nextToken(); } } if (token === 79 /* SyntaxKind.Identifier */ || ts.isKeyword(token)) { token = nextToken(); if (token === 63 /* SyntaxKind.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 === 146 /* SyntaxKind.RequireKeyword */) { token = nextToken(); if (token === 20 /* SyntaxKind.OpenParenToken */) { token = nextToken(); if (token === 10 /* SyntaxKind.StringLiteral */ || allowTemplateLiterals && token === 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */) { // require("mod"); recordModuleName(); } } return true; } return false; } function tryConsumeDefine() { var token = ts.scanner.getToken(); if (token === 79 /* SyntaxKind.Identifier */ && ts.scanner.getTokenValue() === "define") { token = nextToken(); if (token !== 20 /* SyntaxKind.OpenParenToken */) { return true; } token = nextToken(); if (token === 10 /* SyntaxKind.StringLiteral */ || token === 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */) { // looks like define ("modname", ... - skip string literal and comma token = nextToken(); if (token === 27 /* SyntaxKind.CommaToken */) { token = nextToken(); } else { // unexpected token return true; } } // should be start of dependency list if (token !== 22 /* SyntaxKind.OpenBracketToken */) { return true; } // skip open bracket token = nextToken(); // scan until ']' or EOF while (token !== 23 /* SyntaxKind.CloseBracketToken */ && token !== 1 /* SyntaxKind.EndOfFileToken */) { // record string literals as module names if (token === 10 /* SyntaxKind.StringLiteral */ || token === 14 /* SyntaxKind.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 /* SyntaxKind.EndOfFileToken */) { break; } if (ts.scanner.getToken() === 15 /* SyntaxKind.TemplateHead */) { var stack = [ts.scanner.getToken()]; var token = ts.scanner.scan(); loop: while (ts.length(stack)) { switch (token) { case 1 /* SyntaxKind.EndOfFileToken */: break loop; case 100 /* SyntaxKind.ImportKeyword */: tryConsumeImport(); break; case 15 /* SyntaxKind.TemplateHead */: stack.push(token); break; case 18 /* SyntaxKind.OpenBraceToken */: if (ts.length(stack)) { stack.push(token); } break; case 19 /* SyntaxKind.CloseBraceToken */: if (ts.length(stack)) { if (ts.lastOrUndefined(stack) === 15 /* SyntaxKind.TemplateHead */) { if (ts.scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === 17 /* SyntaxKind.TemplateTail */) { stack.pop(); } } else { stack.pop(); } } break; } token = ts.scanner.scan(); } nextToken(); } // 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, program, options); if (renameInfo) { return renameInfo; } } return getRenameInfoError(ts.Diagnostics.You_cannot_rename_this_element); } Rename.getRenameInfo = getRenameInfo; function getRenameInfoForNode(node, typeChecker, sourceFile, program, options) { var symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { if (ts.isStringLiteralLike(node)) { var type = ts.getContextualTypeFromParentOrAncestorTypeNode(node, typeChecker); if (type && ((type.flags & 128 /* TypeFlags.StringLiteral */) || ((type.flags & 1048576 /* TypeFlags.Union */) && ts.every(type.types, function (type) { return !!(type.flags & 128 /* TypeFlags.StringLiteral */); })))) { return getRenameInfoSuccess(node.text, node.text, "string" /* ScriptElementKind.string */, "", node, sourceFile); } } else if (ts.isLabelName(node)) { var name = ts.getTextOfNode(node); return getRenameInfoSuccess(name, name, "label" /* ScriptElementKind.label */, "" /* ScriptElementKindModifier.none */, node, sourceFile); } return undefined; } // 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(function (declaration) { return isDefinedInLibraryFile(program, declaration); })) { 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 === 88 /* SyntaxKind.DefaultKeyword */ && symbol.parent && symbol.parent.flags & 1536 /* SymbolFlags.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 === 162 /* SyntaxKind.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(typeChecker, symbol), node, sourceFile); } function isDefinedInLibraryFile(program, declaration) { var sourceFile = declaration.getSourceFile(); return program.isSourceFileDefaultLibrary(sourceFile) && ts.fileExtensionIs(sourceFile.fileName, ".d.ts" /* Extension.Dts */); } 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 = moduleSymbol.declarations && 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" /* ScriptElementKind.moduleElement */ : "directory" /* ScriptElementKind.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: "" /* ScriptElementKindModifier.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 79 /* SyntaxKind.Identifier */: case 80 /* SyntaxKind.PrivateIdentifier */: case 10 /* SyntaxKind.StringLiteral */: case 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */: case 108 /* SyntaxKind.ThisKeyword */: return true; case 8 /* SyntaxKind.NumericLiteral */: return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node); default: return false; } } Rename.nodeIsEligibleForRename = nodeIsEligibleForRename; })(Rename = ts.Rename || (ts.Rename = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var SmartSelectionRange; (function (SmartSelectionRange) { function getSmartSelectionRange(pos, sourceFile) { var _a; 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 (ts.getTokenPosOfNode(node, sourceFile, /*includeJsDoc*/ true) > pos) { break outer; } var comment = ts.singleOrUndefined(ts.getTrailingCommentRanges(sourceFile.text, node.end)); if (comment && comment.kind === 2 /* SyntaxKind.SingleLineCommentTrivia */) { pushSelectionCommentRange(comment.pos, comment.end); } 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 || ts.isJSDocTypeExpression(node) || ts.isJSDocSignature(node) || ts.isJSDocTypeLiteral(node)) { parentNode = node; break; } // Synthesize a stop for '${ ... }' since '${' and '}' actually belong to siblings. if (ts.isTemplateSpan(parentNode) && nextNode && ts.isTemplateMiddleOrTemplateTail(nextNode)) { var start_1 = node.getFullStart() - "${".length; var end_2 = nextNode.getStart() + "}".length; pushSelectionRange(start_1, 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 start = isBetweenMultiLineBookends ? prevNode.getEnd() : node.getStart(); var end = isBetweenMultiLineBookends ? nextNode.getStart() : getEndPos(sourceFile, node); if (ts.hasJSDocNodes(node) && ((_a = node.jsDoc) === null || _a === void 0 ? void 0 : _a.length)) { pushSelectionRange(ts.first(node.jsDoc).getStart(), 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 }); } } } function pushSelectionCommentRange(start, end) { pushSelectionRange(start, end); var pos = start; while (sourceFile.text.charCodeAt(pos) === 47 /* CharacterCodes.slash */) { pos++; } pushSelectionRange(pos, end); } } 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 /* SyntaxKind.OpenBraceToken */); ts.Debug.assertEqual(closeBraceToken.kind, 19 /* SyntaxKind.CloseBraceToken */); // Group `-/+readonly` and `-/+?` var groupedWithPlusMinusTokens = groupChildren(children, function (child) { return child === node.readonlyToken || child.kind === 145 /* SyntaxKind.ReadonlyKeyword */ || child === node.questionToken || child.kind === 57 /* SyntaxKind.QuestionToken */; }); // Group type parameter with surrounding brackets var groupedWithBrackets = groupChildren(groupedWithPlusMinusTokens, function (_a) { var kind = _a.kind; return kind === 22 /* SyntaxKind.OpenBracketToken */ || kind === 163 /* SyntaxKind.TypeParameter */ || kind === 23 /* SyntaxKind.CloseBracketToken */; }); return [ openBraceToken, // Pivot on `:` createSyntaxList(splitChildren(groupedWithBrackets, function (_a) { var kind = _a.kind; return kind === 58 /* SyntaxKind.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 /* SyntaxKind.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 === 63 /* SyntaxKind.EqualsToken */; }); } // Pivot on '=' if (ts.isBindingElement(node)) { return splitChildren(node.getChildren(), function (_a) { var kind = _a.kind; return kind === 63 /* SyntaxKind.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 /* SyntaxKind.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); return ts.setTextRangePosEnd(ts.parseNodeFactory.createSyntaxList(children), children[0].pos, ts.last(children).end); } function isListOpener(token) { var kind = token && token.kind; return kind === 18 /* SyntaxKind.OpenBraceToken */ || kind === 22 /* SyntaxKind.OpenBracketToken */ || kind === 20 /* SyntaxKind.OpenParenToken */ || kind === 280 /* SyntaxKind.JsxOpeningElement */; } function isListCloser(token) { var kind = token && token.kind; return kind === 19 /* SyntaxKind.CloseBraceToken */ || kind === 23 /* SyntaxKind.CloseBracketToken */ || kind === 21 /* SyntaxKind.CloseParenToken */ || kind === 281 /* SyntaxKind.JsxClosingElement */; } function getEndPos(sourceFile, node) { switch (node.kind) { case 340 /* SyntaxKind.JSDocParameterTag */: case 338 /* SyntaxKind.JSDocCallbackTag */: case 347 /* SyntaxKind.JSDocPropertyTag */: case 345 /* SyntaxKind.JSDocTypedefTag */: case 342 /* SyntaxKind.JSDocThisTag */: return sourceFile.getLineEndOfPosition(node.getStart()); default: return node.getEnd(); } } })(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 /* CandidateOrTypeKind.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 /* InvocationKind.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 /* CandidateOrTypeKind.Candidate */, candidates: candidates, resolvedSignature: resolvedSignature }; } case 1 /* InvocationKind.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 /* CandidateOrTypeKind.Candidate */, candidates: candidates, resolvedSignature: ts.first(candidates) }; var symbol = checker.getSymbolAtLocation(called); return symbol && { kind: 1 /* CandidateOrTypeKind.Type */, symbol: symbol }; } case 2 /* InvocationKind.Contextual */: return { kind: 0 /* CandidateOrTypeKind.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 /* SyntaxKind.OpenParenToken */: return ts.contains(invocationChildren, startingToken); case 27 /* SyntaxKind.CommaToken */: { var containingList = ts.findContainingList(startingToken); return !!containingList && ts.contains(invocationChildren, containingList); } case 29 /* SyntaxKind.LessThanToken */: return containsPrecedingToken(startingToken, sourceFile, node.expression); default: return false; } } function createJSSignatureHelpItems(argumentInfo, program, cancellationToken) { if (argumentInfo.invocation.kind === 2 /* InvocationKind.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.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, /*useFullPrefix*/ true); }); } }); }); } 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 /* InvocationKind.Call */ ? undefined : { invocation: info.invocation.node, argumentCount: info.argumentCount, argumentIndex: info.argumentIndex }; } SignatureHelp.getArgumentInfoForCompletions = getArgumentInfoForCompletions; function getArgumentOrParameterListInfo(node, position, sourceFile) { var info = getArgumentOrParameterListAndIndex(node, sourceFile); if (!info) return undefined; var list = info.list, argumentIndex = info.argumentIndex; var argumentCount = getArgumentCount(list, /*ignoreTrailingComma*/ ts.isInString(sourceFile, position, node)); 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 /* SyntaxKind.LessThanToken */ || node.kind === 20 /* SyntaxKind.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, position, 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 /* InvocationKind.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 === 210 /* SyntaxKind.TaggedTemplateExpression */) { var templateExpression = parent; var tagExpression = templateExpression.parent; ts.Debug.assert(templateExpression.kind === 223 /* SyntaxKind.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 /* SyntaxKind.CommaToken */; }); if (!ignoreTrailingComma && listChildren.length > 0 && ts.last(listChildren).kind === 27 /* SyntaxKind.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 /* InvocationKind.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 === 223 /* SyntaxKind.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_9 = 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: ".concat(ts.Debug.formatSyntaxKind(n.kind), ", parent: ").concat(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_4 = _loop_9(n); if (typeof state_4 === "object") return state_4.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 /* InvocationKind.Call */ ? ts.getInvokedExpression(invocation.node) : invocation.called; } function getEnclosingDeclarationFromInvocation(invocation) { return invocation.kind === 0 /* InvocationKind.Call */ ? invocation.node : invocation.kind === 1 /* InvocationKind.TypeArgs */ ? invocation.called : invocation.node; } var signatureHelpNodeBuilderFlags = 8192 /* NodeBuilderFlags.OmitParameterModifiers */ | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 16384 /* NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope */; function createSignatureHelpItems(candidates, resolvedSignature, _a, sourceFile, typeChecker, useFullPrefix) { var _b; 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 /* InvocationKind.Contextual */ ? invocation.symbol : (typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation)) || useFullPrefix && ((_b = resolvedSignature.declaration) === null || _b === void 0 ? void 0 : _b.symbol)); var callTargetDisplayParts = callTargetSymbol ? ts.symbolToDisplayParts(typeChecker, callTargetSymbol, useFullPrefix ? sourceFile : undefined, /*meaning*/ undefined) : ts.emptyArray; var items = ts.map(candidates, function (candidateSignature) { return getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, typeChecker, enclosingDeclaration, sourceFile); }); if (argumentIndex !== 0) { ts.Debug.assertLessThan(argumentIndex, argumentCount); } var selectedItemIndex = 0; var itemsSeen = 0; for (var i = 0; i < items.length; i++) { var item = items[i]; if (candidates[i] === resolvedSignature) { selectedItemIndex = itemsSeen; if (item.length > 1) { // check to see if any items in the list better match than the first one, as the checker isn't filtering the nested lists // (those come from tuple parameter expansion) var count = 0; for (var _i = 0, item_1 = item; _i < item_1.length; _i++) { var i_1 = item_1[_i]; if (i_1.isVariadic || i_1.parameters.length >= argumentCount) { selectedItemIndex = itemsSeen + count; break; } count++; } } } itemsSeen += item.length; } 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. var help = { items: ts.flatMapToMutable(items, ts.identity), applicableSpan: applicableSpan, selectedItemIndex: selectedItemIndex, argumentIndex: argumentIndex, argumentCount: argumentCount }; var selected = help.items[selectedItemIndex]; if (selected.isVariadic) { var firstRest = ts.findIndex(selected.parameters, function (p) { return !!p.isRest; }); if (-1 < firstRest && firstRest < selected.parameters.length - 1) { // We don't have any code to get this correct; instead, don't highlight a current parameter AT ALL help.argumentIndex = selected.parameters.length; } else { help.argumentIndex = Math.min(help.argumentIndex, selected.parameters.length - 1); } } return help; } 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(checker); var prefixDisplayParts = __spreadArray(__spreadArray([], typeSymbolDisplay, true), [ts.punctuationPart(29 /* SyntaxKind.LessThanToken */)], false); return { isVariadic: false, prefixDisplayParts: prefixDisplayParts, suffixDisplayParts: [ts.punctuationPart(31 /* SyntaxKind.GreaterThanToken */)], separatorDisplayParts: separatorDisplayParts, parameters: parameters, documentation: documentation, tags: tags }; } var separatorDisplayParts = [ts.punctuationPart(27 /* SyntaxKind.CommaToken */), ts.spacePart()]; function getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, checker, enclosingDeclaration, sourceFile) { var infos = (isTypeParameterList ? itemInfoForTypeParameters : itemInfoForParameters)(candidateSignature, checker, enclosingDeclaration, sourceFile); return ts.map(infos, function (_a) { var isVariadic = _a.isVariadic, parameters = _a.parameters, prefix = _a.prefix, suffix = _a.suffix; var prefixDisplayParts = __spreadArray(__spreadArray([], callTargetDisplayParts, true), prefix, true); var suffixDisplayParts = __spreadArray(__spreadArray([], suffix, true), returnTypeToDisplayParts(candidateSignature, enclosingDeclaration, checker), true); 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 thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)] : []; return checker.getExpandedParameters(candidateSignature).map(function (paramList) { var params = ts.factory.createNodeArray(__spreadArray(__spreadArray([], thisParameter, true), ts.map(paramList, function (param) { return checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags); }), true)); var parameterParts = ts.mapToDisplayParts(function (writer) { printer.writeList(2576 /* ListFormat.CallExpressionArguments */, params, sourceFile, writer); }); return { isVariadic: false, parameters: parameters, prefix: [ts.punctuationPart(29 /* SyntaxKind.LessThanToken */)], suffix: __spreadArray([ts.punctuationPart(31 /* SyntaxKind.GreaterThanToken */)], parameterParts, true) }; }); } function itemInfoForParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { var printer = ts.createPrinter({ removeComments: true }); var typeParameterParts = ts.mapToDisplayParts(function (writer) { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { var args = ts.factory.createNodeArray(candidateSignature.typeParameters.map(function (p) { return checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags); })); printer.writeList(53776 /* ListFormat.TypeParameters */, args, sourceFile, writer); } }); var lists = checker.getExpandedParameters(candidateSignature); var isVariadic = !checker.hasEffectiveRestParameter(candidateSignature) ? function (_) { return false; } : lists.length === 1 ? function (_) { return true; } : function (pList) { return !!(pList.length && pList[pList.length - 1].checkFlags & 32768 /* CheckFlags.RestParameter */); }; return lists.map(function (parameterList) { return ({ isVariadic: isVariadic(parameterList), parameters: parameterList.map(function (p) { return createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer); }), prefix: __spreadArray(__spreadArray([], typeParameterParts, true), [ts.punctuationPart(20 /* SyntaxKind.OpenParenToken */)], false), suffix: [ts.punctuationPart(21 /* SyntaxKind.CloseParenToken */)] }); }); } function createSignatureHelpParameterForParameter(parameter, checker, enclosingDeclaration, sourceFile, printer) { var displayParts = ts.mapToDisplayParts(function (writer) { var param = checker.symbolToParameterDeclaration(parameter, enclosingDeclaration, signatureHelpNodeBuilderFlags); printer.writeNode(4 /* EmitHint.Unspecified */, param, sourceFile, writer); }); var isOptional = checker.isOptionalParameter(parameter.valueDeclaration); var isRest = !!(parameter.checkFlags & 32768 /* CheckFlags.RestParameter */); return { name: parameter.name, documentation: parameter.getDocumentationComment(checker), displayParts: displayParts, isOptional: isOptional, isRest: isRest }; } function createSignatureHelpParameterForTypeParameter(typeParameter, checker, enclosingDeclaration, sourceFile, printer) { var displayParts = ts.mapToDisplayParts(function (writer) { var param = checker.typeParameterToDeclaration(typeParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags); printer.writeNode(4 /* EmitHint.Unspecified */, param, sourceFile, writer); }); return { name: typeParameter.symbol.name, documentation: typeParameter.symbol.getDocumentationComment(checker), displayParts: displayParts, isOptional: false, isRest: false }; } })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var InlayHints; (function (InlayHints) { var maxHintsLength = 30; var leadingParameterNameCommentRegexFactory = function (name) { return new RegExp("^\\s?/\\*\\*?\\s?".concat(name, "\\s?\\*\\/\\s?$")); }; function shouldShowParameterNameHints(preferences) { return preferences.includeInlayParameterNameHints === "literals" || preferences.includeInlayParameterNameHints === "all"; } function shouldShowLiteralParameterNameHintsOnly(preferences) { return preferences.includeInlayParameterNameHints === "literals"; } function provideInlayHints(context) { var file = context.file, program = context.program, span = context.span, cancellationToken = context.cancellationToken, preferences = context.preferences; var sourceFileText = file.text; var compilerOptions = program.getCompilerOptions(); var checker = program.getTypeChecker(); var result = []; visitor(file); return result; function visitor(node) { if (!node || node.getFullWidth() === 0) { return; } switch (node.kind) { case 261 /* SyntaxKind.ModuleDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 256 /* SyntaxKind.FunctionDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 213 /* SyntaxKind.FunctionExpression */: case 169 /* SyntaxKind.MethodDeclaration */: case 214 /* SyntaxKind.ArrowFunction */: cancellationToken.throwIfCancellationRequested(); } if (!ts.textSpanIntersectsWith(span, node.pos, node.getFullWidth())) { return; } if (ts.isTypeNode(node)) { return; } if (preferences.includeInlayVariableTypeHints && ts.isVariableDeclaration(node)) { visitVariableLikeDeclaration(node); } else if (preferences.includeInlayPropertyDeclarationTypeHints && ts.isPropertyDeclaration(node)) { visitVariableLikeDeclaration(node); } else if (preferences.includeInlayEnumMemberValueHints && ts.isEnumMember(node)) { visitEnumMember(node); } else if (shouldShowParameterNameHints(preferences) && (ts.isCallExpression(node) || ts.isNewExpression(node))) { visitCallOrNewExpression(node); } else { if (preferences.includeInlayFunctionParameterTypeHints && ts.isFunctionLikeDeclaration(node) && ts.hasContextSensitiveParameters(node)) { visitFunctionLikeForParameterType(node); } if (preferences.includeInlayFunctionLikeReturnTypeHints && isSignatureSupportingReturnAnnotation(node)) { visitFunctionDeclarationLikeForReturnType(node); } } return ts.forEachChild(node, visitor); } function isSignatureSupportingReturnAnnotation(node) { return ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node); } function addParameterHints(text, position, isFirstVariadicArgument) { result.push({ text: "".concat(isFirstVariadicArgument ? "..." : "").concat(truncation(text, maxHintsLength), ":"), position: position, kind: "Parameter" /* InlayHintKind.Parameter */, whitespaceAfter: true, }); } function addTypeHints(text, position) { result.push({ text: ": ".concat(truncation(text, maxHintsLength)), position: position, kind: "Type" /* InlayHintKind.Type */, whitespaceBefore: true, }); } function addEnumMemberValueHints(text, position) { result.push({ text: "= ".concat(truncation(text, maxHintsLength)), position: position, kind: "Enum" /* InlayHintKind.Enum */, whitespaceBefore: true, }); } function visitEnumMember(member) { if (member.initializer) { return; } var enumValue = checker.getConstantValue(member); if (enumValue !== undefined) { addEnumMemberValueHints(enumValue.toString(), member.end); } } function isModuleReferenceType(type) { return type.symbol && (type.symbol.flags & 1536 /* SymbolFlags.Module */); } function visitVariableLikeDeclaration(decl) { if (!decl.initializer || ts.isBindingPattern(decl.name)) { return; } var effectiveTypeAnnotation = ts.getEffectiveTypeAnnotationNode(decl); if (effectiveTypeAnnotation) { return; } var declarationType = checker.getTypeAtLocation(decl); if (isModuleReferenceType(declarationType)) { return; } var typeDisplayString = printTypeInSingleLine(declarationType); if (typeDisplayString) { addTypeHints(typeDisplayString, decl.name.end); } } function visitCallOrNewExpression(expr) { var args = expr.arguments; if (!args || !args.length) { return; } var candidates = []; var signature = checker.getResolvedSignatureForSignatureHelp(expr, candidates); if (!signature || !candidates.length) { return; } for (var i = 0; i < args.length; ++i) { var originalArg = args[i]; var arg = ts.skipParentheses(originalArg); if (shouldShowLiteralParameterNameHintsOnly(preferences) && !isHintableLiteral(arg)) { continue; } var identifierNameInfo = checker.getParameterIdentifierNameAtPosition(signature, i); if (identifierNameInfo) { var parameterName = identifierNameInfo[0], isFirstVariadicArgument = identifierNameInfo[1]; var isParameterNameNotSameAsArgument = preferences.includeInlayParameterNameHintsWhenArgumentMatchesName || !identifierOrAccessExpressionPostfixMatchesParameterName(arg, parameterName); if (!isParameterNameNotSameAsArgument && !isFirstVariadicArgument) { continue; } var name = ts.unescapeLeadingUnderscores(parameterName); if (leadingCommentsContainsParameterName(arg, name)) { continue; } addParameterHints(name, originalArg.getStart(), isFirstVariadicArgument); } } } function identifierOrAccessExpressionPostfixMatchesParameterName(expr, parameterName) { if (ts.isIdentifier(expr)) { return expr.text === parameterName; } if (ts.isPropertyAccessExpression(expr)) { return expr.name.text === parameterName; } return false; } function leadingCommentsContainsParameterName(node, name) { if (!ts.isIdentifierText(name, compilerOptions.target, ts.getLanguageVariant(file.scriptKind))) { return false; } var ranges = ts.getLeadingCommentRanges(sourceFileText, node.pos); if (!(ranges === null || ranges === void 0 ? void 0 : ranges.length)) { return false; } var regex = leadingParameterNameCommentRegexFactory(name); return ts.some(ranges, function (range) { return regex.test(sourceFileText.substring(range.pos, range.end)); }); } function isHintableLiteral(node) { switch (node.kind) { case 219 /* SyntaxKind.PrefixUnaryExpression */: { var operand = node.operand; return ts.isLiteralExpression(operand) || ts.isIdentifier(operand) && ts.isInfinityOrNaNString(operand.escapedText); } case 110 /* SyntaxKind.TrueKeyword */: case 95 /* SyntaxKind.FalseKeyword */: case 104 /* SyntaxKind.NullKeyword */: case 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */: case 223 /* SyntaxKind.TemplateExpression */: return true; case 79 /* SyntaxKind.Identifier */: { var name = node.escapedText; return isUndefined(name) || ts.isInfinityOrNaNString(name); } } return ts.isLiteralExpression(node); } function visitFunctionDeclarationLikeForReturnType(decl) { if (ts.isArrowFunction(decl)) { if (!ts.findChildOfKind(decl, 20 /* SyntaxKind.OpenParenToken */, file)) { return; } } var effectiveTypeAnnotation = ts.getEffectiveReturnTypeNode(decl); if (effectiveTypeAnnotation || !decl.body) { return; } var signature = checker.getSignatureFromDeclaration(decl); if (!signature) { return; } var returnType = checker.getReturnTypeOfSignature(signature); if (isModuleReferenceType(returnType)) { return; } var typeDisplayString = printTypeInSingleLine(returnType); if (!typeDisplayString) { return; } addTypeHints(typeDisplayString, getTypeAnnotationPosition(decl)); } function getTypeAnnotationPosition(decl) { var closeParenToken = ts.findChildOfKind(decl, 21 /* SyntaxKind.CloseParenToken */, file); if (closeParenToken) { return closeParenToken.end; } return decl.parameters.end; } function visitFunctionLikeForParameterType(node) { var signature = checker.getSignatureFromDeclaration(node); if (!signature) { return; } for (var i = 0; i < node.parameters.length && i < signature.parameters.length; ++i) { var param = node.parameters[i]; var effectiveTypeAnnotation = ts.getEffectiveTypeAnnotationNode(param); if (effectiveTypeAnnotation) { continue; } var typeDisplayString = getParameterDeclarationTypeDisplayString(signature.parameters[i]); if (!typeDisplayString) { continue; } addTypeHints(typeDisplayString, param.questionToken ? param.questionToken.end : param.name.end); } } function getParameterDeclarationTypeDisplayString(symbol) { var valueDeclaration = symbol.valueDeclaration; if (!valueDeclaration || !ts.isParameter(valueDeclaration)) { return undefined; } var signatureParamType = checker.getTypeOfSymbolAtLocation(symbol, valueDeclaration); if (isModuleReferenceType(signatureParamType)) { return undefined; } return printTypeInSingleLine(signatureParamType); } function truncation(text, maxLength) { if (text.length > maxLength) { return text.substr(0, maxLength - "...".length) + "..."; } return text; } function printTypeInSingleLine(type) { var flags = 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 1048576 /* TypeFormatFlags.AllowUniqueESSymbolType */ | 16384 /* TypeFormatFlags.UseAliasDefinedOutsideCurrentScope */; var options = { removeComments: true }; var printer = ts.createPrinter(options); return ts.usingSingleLineStringWriter(function (writer) { var typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer); ts.Debug.assertIsDefined(typeNode, "should always get typenode"); printer.writeNode(4 /* EmitHint.Unspecified */, typeNode, /*sourceFile*/ file, writer); }); } function isUndefined(name) { return name === "undefined"; } } InlayHints.provideInlayHints = provideInlayHints; })(InlayHints = ts.InlayHints || (ts.InlayHints = {})); })(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 = new ts.Map(); var documentPositionMappers = new ts.Map(); 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 = ts.outFile(options); var declarationPath = outPath ? ts.removeFileExtension(outPath) + ".d.ts" /* Extension.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 = new ts.Map(); function computeSuggestionDiagnostics(sourceFile, program, cancellationToken) { program.getSemanticDiagnostics(sourceFile, cancellationToken); var diags = []; var checker = program.getTypeChecker(); var isCommonJSFile = sourceFile.impliedNodeFormat === ts.ModuleKind.CommonJS || ts.fileExtensionIsOneOf(sourceFile.fileName, [".cts" /* Extension.Cts */, ".cjs" /* Extension.Cjs */]); if (!isCommonJSFile && sourceFile.commonJsModuleIndicator && (ts.programContainsEsModules(program) || ts.compilerOptionsIndicateEsModules(program.getCompilerOptions())) && containsTopLevelCommonjs(sourceFile)) { diags.push(ts.createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), ts.Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES_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, ts.getModeForUsageLocation(sourceFile, moduleSpecifier)); var resolvedFile = module_1 && program.getSourceFile(module_1.resolvedFileName); if (resolvedFile && resolvedFile.externalModuleIndicator && resolvedFile.externalModuleIndicator !== true && 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, checker)) { 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 /* NodeFlags.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 (canBeConvertedToAsync(node)) { addConvertToAsyncFunctionDiagnostics(node, checker, diags); } node.forEachChild(check); } } ts.computeSuggestionDiagnostics = computeSuggestionDiagnostics; // convertToEsModule 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 237 /* SyntaxKind.VariableStatement */: return statement.declarationList.declarations.some(function (decl) { return !!decl.initializer && ts.isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true); }); case 238 /* SyntaxKind.ExpressionStatement */: { var expression = statement.expression; if (!ts.isBinaryExpression(expression)) return ts.isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true); var kind = ts.getAssignmentDeclarationKind(expression); return kind === 1 /* AssignmentDeclarationKind.ExportsProperty */ || kind === 2 /* AssignmentDeclarationKind.ModuleExports */; } default: return false; } }); } function propertyAccessLeftHandSide(node) { return ts.isPropertyAccessExpression(node) ? propertyAccessLeftHandSide(node.expression) : node; } function importNameForConvertToDefaultImport(node) { switch (node.kind) { case 266 /* SyntaxKind.ImportDeclaration */: var importClause = node.importClause, moduleSpecifier = node.moduleSpecifier; return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === 268 /* SyntaxKind.NamespaceImport */ && ts.isStringLiteral(moduleSpecifier) ? importClause.namedBindings.name : undefined; case 265 /* SyntaxKind.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, checker) && returnsPromise(node, checker); } function returnsPromise(node, checker) { var signature = checker.getSignatureFromDeclaration(node); var returnType = signature ? checker.getReturnTypeOfSignature(signature) : undefined; return !!returnType && !!checker.getPromisedTypeOfPromise(returnType); } ts.returnsPromise = returnsPromise; function getErrorNodeFromCommonJsIndicator(commonJsModuleIndicator) { return ts.isBinaryExpression(commonJsModuleIndicator) ? commonJsModuleIndicator.left : commonJsModuleIndicator; } function hasReturnStatementWithPromiseHandler(body, checker) { return !!ts.forEachReturnStatement(body, function (statement) { return isReturnStatementWithFixablePromiseHandler(statement, checker); }); } function isReturnStatementWithFixablePromiseHandler(node, checker) { return ts.isReturnStatement(node) && !!node.expression && isFixablePromiseHandler(node.expression, checker); } ts.isReturnStatementWithFixablePromiseHandler = isReturnStatementWithFixablePromiseHandler; // Should be kept up to date with transformExpression in convertToAsyncFunction.ts function isFixablePromiseHandler(node, checker) { // ensure outermost call exists and is a promise handler if (!isPromiseHandler(node) || !hasSupportedNumberOfArguments(node) || !node.arguments.every(function (arg) { return isFixablePromiseArgument(arg, checker); })) { return false; } // ensure all chained calls are valid var currentNode = node.expression.expression; while (isPromiseHandler(currentNode) || ts.isPropertyAccessExpression(currentNode)) { if (ts.isCallExpression(currentNode)) { if (!hasSupportedNumberOfArguments(currentNode) || !currentNode.arguments.every(function (arg) { return isFixablePromiseArgument(arg, checker); })) { return false; } currentNode = currentNode.expression.expression; } else { currentNode = currentNode.expression; } } return true; } ts.isFixablePromiseHandler = isFixablePromiseHandler; function isPromiseHandler(node) { return ts.isCallExpression(node) && (ts.hasPropertyAccessExpressionWithName(node, "then") || ts.hasPropertyAccessExpressionWithName(node, "catch") || ts.hasPropertyAccessExpressionWithName(node, "finally")); } function hasSupportedNumberOfArguments(node) { var name = node.expression.name.text; var maxArguments = name === "then" ? 2 : name === "catch" ? 1 : name === "finally" ? 1 : 0; if (node.arguments.length > maxArguments) return false; if (node.arguments.length < maxArguments) return true; return maxArguments === 1 || ts.some(node.arguments, function (arg) { return arg.kind === 104 /* SyntaxKind.NullKeyword */ || ts.isIdentifier(arg) && arg.text === "undefined"; }); } // should be kept up to date with getTransformationBody in convertToAsyncFunction.ts function isFixablePromiseArgument(arg, checker) { switch (arg.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: var functionFlags = ts.getFunctionFlags(arg); if (functionFlags & 1 /* FunctionFlags.Generator */) { return false; } // falls through case 214 /* SyntaxKind.ArrowFunction */: visitedNestedConvertibleFunctions.set(getKeyFromNode(arg), true); // falls through case 104 /* SyntaxKind.NullKeyword */: return true; case 79 /* SyntaxKind.Identifier */: case 206 /* SyntaxKind.PropertyAccessExpression */: { var symbol = checker.getSymbolAtLocation(arg); if (!symbol) { return false; } return checker.isUndefinedSymbol(symbol) || ts.some(ts.skipAlias(symbol, checker).declarations, function (d) { return ts.isFunctionLike(d) || ts.hasInitializer(d) && !!d.initializer && ts.isFunctionLike(d.initializer); }); } default: return false; } } function getKeyFromNode(exp) { return "".concat(exp.pos.toString(), ":").concat(exp.end.toString()); } function canBeConvertedToClass(node, checker) { var _a, _b, _c, _d; if (node.kind === 213 /* SyntaxKind.FunctionExpression */) { if (ts.isVariableDeclaration(node.parent) && ((_a = node.symbol.members) === null || _a === void 0 ? void 0 : _a.size)) { return true; } var symbol = checker.getSymbolOfExpando(node, /*allowDeclaration*/ false); 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 === 256 /* SyntaxKind.FunctionDeclaration */) { return !!((_d = node.symbol.members) === null || _d === void 0 ? void 0 : _d.size); } return false; } function canBeConvertedToAsync(node) { switch (node.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 169 /* SyntaxKind.MethodDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: return true; default: return false; } } ts.canBeConvertedToAsync = canBeConvertedToAsync; })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var SymbolDisplay; (function (SymbolDisplay) { var symbolDisplayNodeBuilderFlags = 8192 /* NodeBuilderFlags.OmitParameterModifiers */ | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 16384 /* NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope */; // TODO(drosen): use contextual SemanticMeaning. function getSymbolKind(typeChecker, symbol, location) { var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location); if (result !== "" /* ScriptElementKind.unknown */) { return result; } var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol); if (flags & 32 /* SymbolFlags.Class */) { return ts.getDeclarationOfKind(symbol, 226 /* SyntaxKind.ClassExpression */) ? "local class" /* ScriptElementKind.localClassElement */ : "class" /* ScriptElementKind.classElement */; } if (flags & 384 /* SymbolFlags.Enum */) return "enum" /* ScriptElementKind.enumElement */; if (flags & 524288 /* SymbolFlags.TypeAlias */) return "type" /* ScriptElementKind.typeElement */; if (flags & 64 /* SymbolFlags.Interface */) return "interface" /* ScriptElementKind.interfaceElement */; if (flags & 262144 /* SymbolFlags.TypeParameter */) return "type parameter" /* ScriptElementKind.typeParameterElement */; if (flags & 8 /* SymbolFlags.EnumMember */) return "enum member" /* ScriptElementKind.enumMemberElement */; if (flags & 2097152 /* SymbolFlags.Alias */) return "alias" /* ScriptElementKind.alias */; if (flags & 1536 /* SymbolFlags.Module */) return "module" /* ScriptElementKind.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 /* SymbolFlags.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" /* ScriptElementKind.memberFunctionElement */; } if (typeChecker.isUndefinedSymbol(symbol)) { return "var" /* ScriptElementKind.variableElement */; } if (typeChecker.isArgumentsSymbol(symbol)) { return "local var" /* ScriptElementKind.localVariableElement */; } if (location.kind === 108 /* SyntaxKind.ThisKeyword */ && ts.isExpression(location) || ts.isThisInTypeQuery(location)) { return "parameter" /* ScriptElementKind.parameterElement */; } var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol); if (flags & 3 /* SymbolFlags.Variable */) { if (ts.isFirstDeclarationOfSymbolParameter(symbol)) { return "parameter" /* ScriptElementKind.parameterElement */; } else if (symbol.valueDeclaration && ts.isVarConst(symbol.valueDeclaration)) { return "const" /* ScriptElementKind.constElement */; } else if (ts.forEach(symbol.declarations, ts.isLet)) { return "let" /* ScriptElementKind.letElement */; } return isLocalVariableOrFunction(symbol) ? "local var" /* ScriptElementKind.localVariableElement */ : "var" /* ScriptElementKind.variableElement */; } if (flags & 16 /* SymbolFlags.Function */) return isLocalVariableOrFunction(symbol) ? "local function" /* ScriptElementKind.localFunctionElement */ : "function" /* ScriptElementKind.functionElement */; // FIXME: getter and setter use the same symbol. And it is rare to use only setter without getter, so in most cases the symbol always has getter flag. // So, even when the location is just on the declaration of setter, this function returns getter. if (flags & 32768 /* SymbolFlags.GetAccessor */) return "getter" /* ScriptElementKind.memberGetAccessorElement */; if (flags & 65536 /* SymbolFlags.SetAccessor */) return "setter" /* ScriptElementKind.memberSetAccessorElement */; if (flags & 8192 /* SymbolFlags.Method */) return "method" /* ScriptElementKind.memberFunctionElement */; if (flags & 16384 /* SymbolFlags.Constructor */) return "constructor" /* ScriptElementKind.constructorImplementationElement */; if (flags & 4 /* SymbolFlags.Property */) { if (flags & 33554432 /* SymbolFlags.Transient */ && symbol.checkFlags & 6 /* CheckFlags.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 /* SymbolFlags.PropertyOrAccessor */ | 3 /* SymbolFlags.Variable */)) { return "property" /* ScriptElementKind.memberVariableElement */; } }); 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" /* ScriptElementKind.memberFunctionElement */; } return "property" /* ScriptElementKind.memberVariableElement */; } return unionPropertyKind; } return "property" /* ScriptElementKind.memberVariableElement */; } return "" /* ScriptElementKind.unknown */; } function getNormalizedSymbolModifiers(symbol) { if (symbol.declarations && symbol.declarations.length) { var _a = symbol.declarations, declaration = _a[0], declarations = _a.slice(1); // omit deprecated flag if some declarations are not deprecated var excludeFlags = ts.length(declarations) && ts.isDeprecatedDeclaration(declaration) && ts.some(declarations, function (d) { return !ts.isDeprecatedDeclaration(d); }) ? 8192 /* ModifierFlags.Deprecated */ : 0 /* ModifierFlags.None */; var modifiers = ts.getNodeModifiers(declaration, excludeFlags); if (modifiers) { return modifiers.split(","); } } return []; } function getSymbolModifiers(typeChecker, symbol) { if (!symbol) { return "" /* ScriptElementKindModifier.none */; } var modifiers = new ts.Set(getNormalizedSymbolModifiers(symbol)); if (symbol.flags & 2097152 /* SymbolFlags.Alias */) { var resolvedSymbol = typeChecker.getAliasedSymbol(symbol); if (resolvedSymbol !== symbol) { ts.forEach(getNormalizedSymbolModifiers(resolvedSymbol), function (modifier) { modifiers.add(modifier); }); } } if (symbol.flags & 16777216 /* SymbolFlags.Optional */) { modifiers.add("optional" /* ScriptElementKindModifier.optionalModifier */); } return modifiers.size > 0 ? ts.arrayFrom(modifiers.values()).join(",") : "" /* ScriptElementKindModifier.none */; } 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) { var _a; if (semanticMeaning === void 0) { semanticMeaning = ts.getMeaningFromLocation(location); } var displayParts = []; var documentation = []; var tags = []; var symbolFlags = ts.getCombinedLocalAndExportSymbolFlags(symbol); var symbolKind = semanticMeaning & 1 /* SemanticMeaning.Value */ ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) : "" /* ScriptElementKind.unknown */; var hasAddedSymbolInfo = false; var isThisExpression = location.kind === 108 /* SyntaxKind.ThisKeyword */ && ts.isInExpressionContext(location) || ts.isThisInTypeQuery(location); var type; var printer; var documentationFromAlias; var tagsFromAlias; var hasMultipleSignatures = false; if (location.kind === 108 /* SyntaxKind.ThisKeyword */ && !isThisExpression) { return { displayParts: [ts.keywordPart(108 /* SyntaxKind.ThisKeyword */)], documentation: [], symbolKind: "primitive type" /* ScriptElementKind.primitiveType */, tags: undefined }; } // Class at constructor site need to be shown as constructor apart from property,method, vars if (symbolKind !== "" /* ScriptElementKind.unknown */ || symbolFlags & 32 /* SymbolFlags.Class */ || symbolFlags & 2097152 /* SymbolFlags.Alias */) { // If symbol is accessor, they are allowed only if location is at declaration identifier of the accessor if (symbolKind === "getter" /* ScriptElementKind.memberGetAccessorElement */ || symbolKind === "setter" /* ScriptElementKind.memberSetAccessorElement */) { var declaration = ts.find(symbol.declarations, function (declaration) { return declaration.name === location; }); if (declaration) { switch (declaration.kind) { case 172 /* SyntaxKind.GetAccessor */: symbolKind = "getter" /* ScriptElementKind.memberGetAccessorElement */; break; case 173 /* SyntaxKind.SetAccessor */: symbolKind = "setter" /* ScriptElementKind.memberSetAccessorElement */; break; default: ts.Debug.assertNever(declaration); } } else { symbolKind = "property" /* ScriptElementKind.memberVariableElement */; } } var signature = void 0; type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (location.parent && location.parent.kind === 206 /* SyntaxKind.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.isTaggedTemplateExpression(location.parent)) && ts.isFunctionLike(symbol.valueDeclaration)) { callExpressionLike = location.parent; } if (callExpressionLike) { signature = typeChecker.getResolvedSignature(callExpressionLike); // TODO: GH#18217 var useConstructSignatures = callExpressionLike.kind === 209 /* SyntaxKind.NewExpression */ || (ts.isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === 106 /* SyntaxKind.SuperKeyword */); var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); if (signature && !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 /* SymbolFlags.Class */)) { // Constructor symbolKind = "constructor" /* ScriptElementKind.constructorImplementationElement */; addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } else if (symbolFlags & 2097152 /* SymbolFlags.Alias */) { symbolKind = "alias" /* ScriptElementKind.alias */; pushSymbolKind(symbolKind); displayParts.push(ts.spacePart()); if (useConstructSignatures) { if (signature.flags & 4 /* SignatureFlags.Abstract */) { displayParts.push(ts.keywordPart(126 /* SyntaxKind.AbstractKeyword */)); displayParts.push(ts.spacePart()); } displayParts.push(ts.keywordPart(103 /* SyntaxKind.NewKeyword */)); displayParts.push(ts.spacePart()); } addFullSymbolName(symbol); } else { addPrefixForAnyFunctionOrVar(symbol, symbolKind); } switch (symbolKind) { case "JSX attribute" /* ScriptElementKind.jsxAttribute */: case "property" /* ScriptElementKind.memberVariableElement */: case "var" /* ScriptElementKind.variableElement */: case "const" /* ScriptElementKind.constElement */: case "let" /* ScriptElementKind.letElement */: case "parameter" /* ScriptElementKind.parameterElement */: case "local var" /* ScriptElementKind.localVariableElement */: // If it is call or construct signature of lambda's write type name displayParts.push(ts.punctuationPart(58 /* SyntaxKind.ColonToken */)); displayParts.push(ts.spacePart()); if (!(ts.getObjectFlags(type) & 16 /* ObjectFlags.Anonymous */) && type.symbol) { ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 4 /* SymbolFormatFlags.AllowAnyNodeKind */ | 1 /* SymbolFormatFlags.WriteTypeParametersOrArguments */)); displayParts.push(ts.lineBreakPart()); } if (useConstructSignatures) { if (signature.flags & 4 /* SignatureFlags.Abstract */) { displayParts.push(ts.keywordPart(126 /* SyntaxKind.AbstractKeyword */)); displayParts.push(ts.spacePart()); } displayParts.push(ts.keywordPart(103 /* SyntaxKind.NewKeyword */)); displayParts.push(ts.spacePart()); } addSignatureDisplayParts(signature, allSignatures, 262144 /* TypeFormatFlags.WriteArrowStyleSignature */); break; default: // Just signature addSignatureDisplayParts(signature, allSignatures); } hasAddedSymbolInfo = true; hasMultipleSignatures = allSignatures.length > 1; } } else if ((ts.isNameOfFunctionDeclaration(location) && !(symbolFlags & 98304 /* SymbolFlags.Accessor */)) || // name of function declaration (location.kind === 134 /* SyntaxKind.ConstructorKeyword */ && location.parent.kind === 171 /* SyntaxKind.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 === 134 /* SyntaxKind.ConstructorKeyword */ ? functionDeclaration_1.parent : functionDeclaration_1); }); if (locationIsSymbolDeclaration) { var allSignatures = functionDeclaration_1.kind === 171 /* SyntaxKind.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 === 171 /* SyntaxKind.Constructor */) { // show (constructor) Type(...) signature symbolKind = "constructor" /* ScriptElementKind.constructorImplementationElement */; addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } else { // (function/method) symbol(..signature) addPrefixForAnyFunctionOrVar(functionDeclaration_1.kind === 174 /* SyntaxKind.CallSignature */ && !(type.symbol.flags & 2048 /* SymbolFlags.TypeLiteral */ || type.symbol.flags & 4096 /* SymbolFlags.ObjectLiteral */) ? type.symbol : symbol, symbolKind); } if (signature) { addSignatureDisplayParts(signature, allSignatures); } hasAddedSymbolInfo = true; hasMultipleSignatures = allSignatures.length > 1; } } } if (symbolFlags & 32 /* SymbolFlags.Class */ && !hasAddedSymbolInfo && !isThisExpression) { addAliasPrefixIfNecessary(); if (ts.getDeclarationOfKind(symbol, 226 /* SyntaxKind.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" /* ScriptElementKind.localClassElement */); } else { // Class declaration has name which is not local. displayParts.push(ts.keywordPart(84 /* SyntaxKind.ClassKeyword */)); } displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); } if ((symbolFlags & 64 /* SymbolFlags.Interface */) && (semanticMeaning & 2 /* SemanticMeaning.Type */)) { prefixNextMeaning(); displayParts.push(ts.keywordPart(118 /* SyntaxKind.InterfaceKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); } if ((symbolFlags & 524288 /* SymbolFlags.TypeAlias */) && (semanticMeaning & 2 /* SemanticMeaning.Type */)) { prefixNextMeaning(); displayParts.push(ts.keywordPart(152 /* SyntaxKind.TypeKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); displayParts.push(ts.spacePart()); displayParts.push(ts.operatorPart(63 /* SyntaxKind.EqualsToken */)); displayParts.push(ts.spacePart()); ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, ts.isConstTypeReference(location.parent) ? typeChecker.getTypeAtLocation(location.parent) : typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 8388608 /* TypeFormatFlags.InTypeAlias */)); } if (symbolFlags & 384 /* SymbolFlags.Enum */) { prefixNextMeaning(); if (ts.some(symbol.declarations, function (d) { return ts.isEnumDeclaration(d) && ts.isEnumConst(d); })) { displayParts.push(ts.keywordPart(85 /* SyntaxKind.ConstKeyword */)); displayParts.push(ts.spacePart()); } displayParts.push(ts.keywordPart(92 /* SyntaxKind.EnumKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); } if (symbolFlags & 1536 /* SymbolFlags.Module */ && !isThisExpression) { prefixNextMeaning(); var declaration = ts.getDeclarationOfKind(symbol, 261 /* SyntaxKind.ModuleDeclaration */); var isNamespace = declaration && declaration.name && declaration.name.kind === 79 /* SyntaxKind.Identifier */; displayParts.push(ts.keywordPart(isNamespace ? 142 /* SyntaxKind.NamespaceKeyword */ : 141 /* SyntaxKind.ModuleKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(symbol); } if ((symbolFlags & 262144 /* SymbolFlags.TypeParameter */) && (semanticMeaning & 2 /* SemanticMeaning.Type */)) { prefixNextMeaning(); displayParts.push(ts.punctuationPart(20 /* SyntaxKind.OpenParenToken */)); displayParts.push(ts.textPart("type parameter")); displayParts.push(ts.punctuationPart(21 /* SyntaxKind.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, 163 /* SyntaxKind.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 === 175 /* SyntaxKind.ConstructSignature */) { displayParts.push(ts.keywordPart(103 /* SyntaxKind.NewKeyword */)); displayParts.push(ts.spacePart()); } else if (declaration.kind !== 174 /* SyntaxKind.CallSignature */ && declaration.name) { addFullSymbolName(declaration.symbol); } ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* TypeFormatFlags.WriteTypeArgumentsOfSignature */)); } else if (declaration.kind === 259 /* SyntaxKind.TypeAliasDeclaration */) { // Type alias type parameter // For example // type list = T[]; // Both T will go through same code path addInPrefix(); displayParts.push(ts.keywordPart(152 /* SyntaxKind.TypeKeyword */)); displayParts.push(ts.spacePart()); addFullSymbolName(declaration.symbol); writeTypeParametersOfSymbol(declaration.symbol, sourceFile); } } } } if (symbolFlags & 8 /* SymbolFlags.EnumMember */) { symbolKind = "enum member" /* ScriptElementKind.enumMemberElement */; addPrefixForAnyFunctionOrVar(symbol, "enum member"); var declaration = (_a = symbol.declarations) === null || _a === void 0 ? void 0 : _a[0]; if ((declaration === null || declaration === void 0 ? void 0 : declaration.kind) === 299 /* SyntaxKind.EnumMember */) { var constantValue = typeChecker.getConstantValue(declaration); if (constantValue !== undefined) { displayParts.push(ts.spacePart()); displayParts.push(ts.operatorPart(63 /* SyntaxKind.EqualsToken */)); displayParts.push(ts.spacePart()); displayParts.push(ts.displayPart(ts.getTextOfConstantValue(constantValue), typeof constantValue === "number" ? ts.SymbolDisplayPartKind.numericLiteral : ts.SymbolDisplayPartKind.stringLiteral)); } } } // don't use symbolFlags since getAliasedSymbol requires the flag on the symbol itself if (symbol.flags & 2097152 /* SymbolFlags.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.hasSyntacticModifier(resolvedNode, 2 /* ModifierFlags.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; } else { documentationFromAlias = resolvedSymbol.getContextualDocumentationComment(resolvedNode, typeChecker); tagsFromAlias = resolvedSymbol.getJsDocTags(typeChecker); } } } if (symbol.declarations) { switch (symbol.declarations[0].kind) { case 264 /* SyntaxKind.NamespaceExportDeclaration */: displayParts.push(ts.keywordPart(93 /* SyntaxKind.ExportKeyword */)); displayParts.push(ts.spacePart()); displayParts.push(ts.keywordPart(142 /* SyntaxKind.NamespaceKeyword */)); break; case 271 /* SyntaxKind.ExportAssignment */: displayParts.push(ts.keywordPart(93 /* SyntaxKind.ExportKeyword */)); displayParts.push(ts.spacePart()); displayParts.push(ts.keywordPart(symbol.declarations[0].isExportEquals ? 63 /* SyntaxKind.EqualsToken */ : 88 /* SyntaxKind.DefaultKeyword */)); break; case 275 /* SyntaxKind.ExportSpecifier */: displayParts.push(ts.keywordPart(93 /* SyntaxKind.ExportKeyword */)); break; default: displayParts.push(ts.keywordPart(100 /* SyntaxKind.ImportKeyword */)); } } displayParts.push(ts.spacePart()); addFullSymbolName(symbol); ts.forEach(symbol.declarations, function (declaration) { if (declaration.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { var importEqualsDeclaration = declaration; if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { displayParts.push(ts.spacePart()); displayParts.push(ts.operatorPart(63 /* SyntaxKind.EqualsToken */)); displayParts.push(ts.spacePart()); displayParts.push(ts.keywordPart(146 /* SyntaxKind.RequireKeyword */)); displayParts.push(ts.punctuationPart(20 /* SyntaxKind.OpenParenToken */)); displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral)); displayParts.push(ts.punctuationPart(21 /* SyntaxKind.CloseParenToken */)); } else { var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(ts.spacePart()); displayParts.push(ts.operatorPart(63 /* SyntaxKind.EqualsToken */)); displayParts.push(ts.spacePart()); addFullSymbolName(internalAliasSymbol, enclosingDeclaration); } } return true; } }); } if (!hasAddedSymbolInfo) { if (symbolKind !== "" /* ScriptElementKind.unknown */) { if (type) { if (isThisExpression) { prefixNextMeaning(); displayParts.push(ts.keywordPart(108 /* SyntaxKind.ThisKeyword */)); } else { addPrefixForAnyFunctionOrVar(symbol, symbolKind); } // For properties, variables and local vars: show the type if (symbolKind === "property" /* ScriptElementKind.memberVariableElement */ || symbolKind === "getter" /* ScriptElementKind.memberGetAccessorElement */ || symbolKind === "setter" /* ScriptElementKind.memberSetAccessorElement */ || symbolKind === "JSX attribute" /* ScriptElementKind.jsxAttribute */ || symbolFlags & 3 /* SymbolFlags.Variable */ || symbolKind === "local var" /* ScriptElementKind.localVariableElement */ || isThisExpression) { displayParts.push(ts.punctuationPart(58 /* SyntaxKind.ColonToken */)); displayParts.push(ts.spacePart()); // If the type is type parameter, format it specially if (type.symbol && type.symbol.flags & 262144 /* SymbolFlags.TypeParameter */) { var typeParameterParts = ts.mapToDisplayParts(function (writer) { var param = typeChecker.typeParameterToDeclaration(type, enclosingDeclaration, symbolDisplayNodeBuilderFlags); getPrinter().writeNode(4 /* EmitHint.Unspecified */, param, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); }); ts.addRange(displayParts, typeParameterParts); } else { ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration)); } if (symbol.target && symbol.target.tupleLabelDeclaration) { var labelDecl = symbol.target.tupleLabelDeclaration; ts.Debug.assertNode(labelDecl.name, ts.isIdentifier); displayParts.push(ts.spacePart()); displayParts.push(ts.punctuationPart(20 /* SyntaxKind.OpenParenToken */)); displayParts.push(ts.textPart(ts.idText(labelDecl.name))); displayParts.push(ts.punctuationPart(21 /* SyntaxKind.CloseParenToken */)); } } else if (symbolFlags & 16 /* SymbolFlags.Function */ || symbolFlags & 8192 /* SymbolFlags.Method */ || symbolFlags & 16384 /* SymbolFlags.Constructor */ || symbolFlags & 131072 /* SymbolFlags.Signature */ || symbolFlags & 98304 /* SymbolFlags.Accessor */ || symbolKind === "method" /* ScriptElementKind.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.getContextualDocumentationComment(enclosingDeclaration, typeChecker); } if (documentation.length === 0 && symbolFlags & 4 /* SymbolFlags.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 && symbol.declarations && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 305 /* SyntaxKind.SourceFile */; })) { for (var _i = 0, _b = symbol.declarations; _i < _b.length; _i++) { var declaration = _b[_i]; if (!declaration.parent || declaration.parent.kind !== 221 /* SyntaxKind.BinaryExpression */) { continue; } var rhsSymbol = typeChecker.getSymbolAtLocation(declaration.parent.right); if (!rhsSymbol) { continue; } documentation = rhsSymbol.getDocumentationComment(typeChecker); tags = rhsSymbol.getJsDocTags(typeChecker); if (documentation.length > 0) { break; } } } } if (documentation.length === 0 && ts.isIdentifier(location) && symbol.valueDeclaration && ts.isBindingElement(symbol.valueDeclaration)) { var declaration = symbol.valueDeclaration; var parent = declaration.parent; if (ts.isIdentifier(declaration.name) && ts.isObjectBindingPattern(parent)) { var name_4 = ts.getTextOfIdentifierOrLiteral(declaration.name); var objectType = typeChecker.getTypeAtLocation(parent); documentation = ts.firstDefined(objectType.isUnion() ? objectType.types : [objectType], function (t) { var prop = t.getProperty(name_4); return prop ? prop.getDocumentationComment(typeChecker) : undefined; }) || ts.emptyArray; } } if (tags.length === 0 && !hasMultipleSignatures) { tags = symbol.getContextualJsDocTags(enclosingDeclaration, typeChecker); } 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" /* ScriptElementKind.alias */); displayParts.push(ts.spacePart()); } } function addInPrefix() { displayParts.push(ts.spacePart()); displayParts.push(ts.keywordPart(101 /* SyntaxKind.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 /* SymbolFormatFlags.WriteTypeParametersOrArguments */ | 2 /* SymbolFormatFlags.UseOnlyExternalAliasing */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); ts.addRange(displayParts, fullSymbolDisplayParts); if (symbol.flags & 16777216 /* SymbolFlags.Optional */) { displayParts.push(ts.punctuationPart(57 /* SyntaxKind.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" /* ScriptElementKind.variableElement */: case "function" /* ScriptElementKind.functionElement */: case "let" /* ScriptElementKind.letElement */: case "const" /* ScriptElementKind.constElement */: case "constructor" /* ScriptElementKind.constructorImplementationElement */: displayParts.push(ts.textOrKeywordPart(symbolKind)); return; default: displayParts.push(ts.punctuationPart(20 /* SyntaxKind.OpenParenToken */)); displayParts.push(ts.textOrKeywordPart(symbolKind)); displayParts.push(ts.punctuationPart(21 /* SyntaxKind.CloseParenToken */)); return; } } function addSignatureDisplayParts(signature, allSignatures, flags) { if (flags === void 0) { flags = 0 /* TypeFormatFlags.None */; } ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* TypeFormatFlags.WriteTypeArgumentsOfSignature */)); if (allSignatures.length > 1) { displayParts.push(ts.spacePart()); displayParts.push(ts.punctuationPart(20 /* SyntaxKind.OpenParenToken */)); displayParts.push(ts.operatorPart(39 /* SyntaxKind.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 /* SyntaxKind.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 /* ListFormat.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 === 213 /* SyntaxKind.FunctionExpression */) { return true; } if (declaration.kind !== 254 /* SyntaxKind.VariableDeclaration */ && declaration.kind !== 256 /* SyntaxKind.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 === 305 /* SyntaxKind.SourceFile */ || parent.kind === 262 /* SyntaxKind.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; var newLine = ts.getNewLineCharacter(options); // 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 []; } }; // 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, { languageVersion: ts.getEmitScriptTarget(options), impliedNodeFormat: ts.getImpliedNodeFormatForFile(ts.toPath(inputFileName, "", compilerHost.getCanonicalFileName), /*cache*/ undefined, compilerHost, options), setExternalModuleIndicator: ts.getSetExternalModuleIndicator(options) }); if (transpileOptions.moduleName) { sourceFile.moduleName = transpileOptions.moduleName; } if (transpileOptions.renamedDependencies) { sourceFile.renamedDependencies = new ts.Map(ts.getEntries(transpileOptions.renamedDependencies)); } // Output var outputText; var sourceMapText; 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_10 = 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_10(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 /* SyntaxKind.OpenBraceToken */, this.sourceFile); var closeBrace = ts.findChildOfKind(node, 19 /* SyntaxKind.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 /* ScriptTarget.Latest */, /*skipTrivia*/ false, 0 /* LanguageVariant.Standard */); var jsxScanner = ts.createScanner(99 /* ScriptTarget.Latest */, /*skipTrivia*/ false, 1 /* LanguageVariant.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 /* LanguageVariant.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, skipToStartOf: skipToStartOf, getStartPos: function () { var _a; return (_a = lastTokenInfo === null || lastTokenInfo === void 0 ? void 0 : lastTokenInfo.token.pos) !== null && _a !== void 0 ? _a : scanner.getTokenPos(); }, }); 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 /* SyntaxKind.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 /* SyntaxKind.GreaterThanEqualsToken */: case 71 /* SyntaxKind.GreaterThanGreaterThanEqualsToken */: case 72 /* SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken */: case 49 /* SyntaxKind.GreaterThanGreaterThanGreaterThanToken */: case 48 /* SyntaxKind.GreaterThanGreaterThanToken */: return true; } return false; } function shouldRescanJsxIdentifier(node) { if (node.parent) { switch (node.parent.kind) { case 285 /* SyntaxKind.JsxAttribute */: case 280 /* SyntaxKind.JsxOpeningElement */: case 281 /* SyntaxKind.JsxClosingElement */: case 279 /* SyntaxKind.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 === 79 /* SyntaxKind.Identifier */; } } return false; } function shouldRescanJsxText(node) { return ts.isJsxText(node); } function shouldRescanSlashToken(container) { return container.kind === 13 /* SyntaxKind.RegularExpressionLiteral */; } function shouldRescanTemplateToken(container) { return container.kind === 16 /* SyntaxKind.TemplateMiddle */ || container.kind === 17 /* SyntaxKind.TemplateTail */; } function shouldRescanJsxAttributeValue(node) { return node.parent && ts.isJsxAttribute(node.parent) && node.parent.initializer === node; } function startsWithSlashToken(t) { return t === 43 /* SyntaxKind.SlashToken */ || t === 68 /* SyntaxKind.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 /* ScanAction.RescanGreaterThanToken */ : shouldRescanSlashToken(n) ? 2 /* ScanAction.RescanSlashToken */ : shouldRescanTemplateToken(n) ? 3 /* ScanAction.RescanTemplateToken */ : shouldRescanJsxIdentifier(n) ? 4 /* ScanAction.RescanJsxIdentifier */ : shouldRescanJsxText(n) ? 5 /* ScanAction.RescanJsxText */ : shouldRescanJsxAttributeValue(n) ? 6 /* ScanAction.RescanJsxAttributeValue */ : 0 /* ScanAction.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 /* SyntaxKind.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 /* ScanAction.Scan */; switch (expectedScanAction) { case 1 /* ScanAction.RescanGreaterThanToken */: if (token === 31 /* SyntaxKind.GreaterThanToken */) { lastScanAction = 1 /* ScanAction.RescanGreaterThanToken */; var newToken = scanner.reScanGreaterToken(); ts.Debug.assert(n.kind === newToken); return newToken; } break; case 2 /* ScanAction.RescanSlashToken */: if (startsWithSlashToken(token)) { lastScanAction = 2 /* ScanAction.RescanSlashToken */; var newToken = scanner.reScanSlashToken(); ts.Debug.assert(n.kind === newToken); return newToken; } break; case 3 /* ScanAction.RescanTemplateToken */: if (token === 19 /* SyntaxKind.CloseBraceToken */) { lastScanAction = 3 /* ScanAction.RescanTemplateToken */; return scanner.reScanTemplateToken(/* isTaggedTemplate */ false); } break; case 4 /* ScanAction.RescanJsxIdentifier */: lastScanAction = 4 /* ScanAction.RescanJsxIdentifier */; return scanner.scanJsxIdentifier(); case 5 /* ScanAction.RescanJsxText */: lastScanAction = 5 /* ScanAction.RescanJsxText */; return scanner.reScanJsxToken(/* allowMultilineJsxText */ false); case 6 /* ScanAction.RescanJsxAttributeValue */: lastScanAction = 6 /* ScanAction.RescanJsxAttributeValue */; return scanner.reScanJsxAttributeValue(); case 0 /* ScanAction.Scan */: break; default: ts.Debug.assertNever(expectedScanAction); } return token; } function readEOFTokenRange() { ts.Debug.assert(isOnEOF()); return formatting.createTextRangeWithKind(scanner.getStartPos(), scanner.getTextPos(), 1 /* SyntaxKind.EndOfFileToken */); } function isOnToken() { var current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken(); return current !== 1 /* SyntaxKind.EndOfFileToken */ && !ts.isTrivia(current); } function isOnEOF() { var current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken(); return current === 1 /* SyntaxKind.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; } function skipToStartOf(node) { scanner.setTextPos(node.pos); 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 /* SyntaxKind.FirstToken */; token <= 160 /* SyntaxKind.LastToken */; token++) { if (token !== 1 /* SyntaxKind.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(__spreadArray(__spreadArray([], allTokens, true), [3 /* SyntaxKind.MultiLineCommentTrivia */], false)); var anyTokenIncludingEOF = tokenRangeFrom(__spreadArray(__spreadArray([], allTokens, true), [1 /* SyntaxKind.EndOfFileToken */], false)); var keywords = tokenRangeFromRange(81 /* SyntaxKind.FirstKeyword */, 160 /* SyntaxKind.LastKeyword */); var binaryOperators = tokenRangeFromRange(29 /* SyntaxKind.FirstBinaryOperator */, 78 /* SyntaxKind.LastBinaryOperator */); var binaryKeywordOperators = [101 /* SyntaxKind.InKeyword */, 102 /* SyntaxKind.InstanceOfKeyword */, 160 /* SyntaxKind.OfKeyword */, 127 /* SyntaxKind.AsKeyword */, 139 /* SyntaxKind.IsKeyword */]; var unaryPrefixOperators = [45 /* SyntaxKind.PlusPlusToken */, 46 /* SyntaxKind.MinusMinusToken */, 54 /* SyntaxKind.TildeToken */, 53 /* SyntaxKind.ExclamationToken */]; var unaryPrefixExpressions = [ 8 /* SyntaxKind.NumericLiteral */, 9 /* SyntaxKind.BigIntLiteral */, 79 /* SyntaxKind.Identifier */, 20 /* SyntaxKind.OpenParenToken */, 22 /* SyntaxKind.OpenBracketToken */, 18 /* SyntaxKind.OpenBraceToken */, 108 /* SyntaxKind.ThisKeyword */, 103 /* SyntaxKind.NewKeyword */ ]; var unaryPreincrementExpressions = [79 /* SyntaxKind.Identifier */, 20 /* SyntaxKind.OpenParenToken */, 108 /* SyntaxKind.ThisKeyword */, 103 /* SyntaxKind.NewKeyword */]; var unaryPostincrementExpressions = [79 /* SyntaxKind.Identifier */, 21 /* SyntaxKind.CloseParenToken */, 23 /* SyntaxKind.CloseBracketToken */, 103 /* SyntaxKind.NewKeyword */]; var unaryPredecrementExpressions = [79 /* SyntaxKind.Identifier */, 20 /* SyntaxKind.OpenParenToken */, 108 /* SyntaxKind.ThisKeyword */, 103 /* SyntaxKind.NewKeyword */]; var unaryPostdecrementExpressions = [79 /* SyntaxKind.Identifier */, 21 /* SyntaxKind.CloseParenToken */, 23 /* SyntaxKind.CloseBracketToken */, 103 /* SyntaxKind.NewKeyword */]; var comments = [2 /* SyntaxKind.SingleLineCommentTrivia */, 3 /* SyntaxKind.MultiLineCommentTrivia */]; var typeNames = __spreadArray([79 /* SyntaxKind.Identifier */], ts.typeKeywords, true); // 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([79 /* SyntaxKind.Identifier */, 3 /* SyntaxKind.MultiLineCommentTrivia */, 84 /* SyntaxKind.ClassKeyword */, 93 /* SyntaxKind.ExportKeyword */, 100 /* SyntaxKind.ImportKeyword */]); // Place a space before open brace in a control flow construct var controlOpenBraceLeftTokenRange = tokenRangeFrom([21 /* SyntaxKind.CloseParenToken */, 3 /* SyntaxKind.MultiLineCommentTrivia */, 90 /* SyntaxKind.DoKeyword */, 111 /* SyntaxKind.TryKeyword */, 96 /* SyntaxKind.FinallyKeyword */, 91 /* SyntaxKind.ElseKeyword */]); // These rules are higher in priority than user-configurable var highPriorityCommonRules = [ // Leave comments alone rule("IgnoreBeforeComment", anyToken, comments, formatting.anyContext, 1 /* RuleAction.StopProcessingSpaceActions */), rule("IgnoreAfterLineComment", 2 /* SyntaxKind.SingleLineCommentTrivia */, anyToken, formatting.anyContext, 1 /* RuleAction.StopProcessingSpaceActions */), rule("NotSpaceBeforeColon", anyToken, 58 /* SyntaxKind.ColonToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceAfterColon", 58 /* SyntaxKind.ColonToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBeforeQuestionMark", anyToken, 57 /* SyntaxKind.QuestionToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], 16 /* RuleAction.DeleteSpace */), // insert space after '?' only when it is used in conditional operator rule("SpaceAfterQuestionMarkInConditionalOperator", 57 /* SyntaxKind.QuestionToken */, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], 4 /* RuleAction.InsertSpace */), // in other cases there should be no space between '?' and next token rule("NoSpaceAfterQuestionMark", 57 /* SyntaxKind.QuestionToken */, anyToken, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeDot", anyToken, [24 /* SyntaxKind.DotToken */, 28 /* SyntaxKind.QuestionDotToken */], [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterDot", [24 /* SyntaxKind.DotToken */, 28 /* SyntaxKind.QuestionDotToken */], anyToken, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBetweenImportParenInImportType", 100 /* SyntaxKind.ImportKeyword */, 20 /* SyntaxKind.OpenParenToken */, [isNonJsxSameLineTokenContext, isImportTypeContext], 16 /* RuleAction.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 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterUnaryPreincrementOperator", 45 /* SyntaxKind.PlusPlusToken */, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterUnaryPredecrementOperator", 46 /* SyntaxKind.MinusMinusToken */, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, 45 /* SyntaxKind.PlusPlusToken */, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, 46 /* SyntaxKind.MinusMinusToken */, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], 16 /* RuleAction.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 /* SyntaxKind.PlusPlusToken */, 39 /* SyntaxKind.PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterAddWhenFollowedByUnaryPlus", 39 /* SyntaxKind.PlusToken */, 39 /* SyntaxKind.PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterAddWhenFollowedByPreincrement", 39 /* SyntaxKind.PlusToken */, 45 /* SyntaxKind.PlusPlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterPostdecrementWhenFollowedBySubtract", 46 /* SyntaxKind.MinusMinusToken */, 40 /* SyntaxKind.MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", 40 /* SyntaxKind.MinusToken */, 40 /* SyntaxKind.MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterSubtractWhenFollowedByPredecrement", 40 /* SyntaxKind.MinusToken */, 46 /* SyntaxKind.MinusMinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterCloseBrace", 19 /* SyntaxKind.CloseBraceToken */, [27 /* SyntaxKind.CommaToken */, 26 /* SyntaxKind.SemicolonToken */], [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // For functions and control block place } on a new line [multi-line rule] rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, 19 /* SyntaxKind.CloseBraceToken */, [isMultilineBlockContext], 8 /* RuleAction.InsertNewLine */), // Space/new line after }. rule("SpaceAfterCloseBrace", 19 /* SyntaxKind.CloseBraceToken */, anyTokenExcept(21 /* SyntaxKind.CloseParenToken */), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], 4 /* RuleAction.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 /* SyntaxKind.CloseBraceToken */, 91 /* SyntaxKind.ElseKeyword */, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBetweenCloseBraceAndWhile", 19 /* SyntaxKind.CloseBraceToken */, 115 /* SyntaxKind.WhileKeyword */, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBetweenEmptyBraceBrackets", 18 /* SyntaxKind.OpenBraceToken */, 19 /* SyntaxKind.CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 16 /* RuleAction.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 /* SyntaxKind.CloseParenToken */, 22 /* SyntaxKind.OpenBracketToken */, [isControlDeclContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBetweenFunctionKeywordAndStar", 98 /* SyntaxKind.FunctionKeyword */, 41 /* SyntaxKind.AsteriskToken */, [isFunctionDeclarationOrFunctionExpressionContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceAfterStarInGeneratorDeclaration", 41 /* SyntaxKind.AsteriskToken */, 79 /* SyntaxKind.Identifier */, [isFunctionDeclarationOrFunctionExpressionContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterFunctionInFuncDecl", 98 /* SyntaxKind.FunctionKeyword */, anyToken, [isFunctionDeclContext], 4 /* RuleAction.InsertSpace */), // Insert new line after { and before } in multi-line contexts. rule("NewLineAfterOpenBraceInBlockContext", 18 /* SyntaxKind.OpenBraceToken */, anyToken, [isMultilineBlockContext], 8 /* RuleAction.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", [136 /* SyntaxKind.GetKeyword */, 149 /* SyntaxKind.SetKeyword */], 79 /* SyntaxKind.Identifier */, [isFunctionDeclContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBetweenYieldKeywordAndStar", 125 /* SyntaxKind.YieldKeyword */, 41 /* SyntaxKind.AsteriskToken */, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 16 /* RuleAction.DeleteSpace */), rule("SpaceBetweenYieldOrYieldStarAndOperand", [125 /* SyntaxKind.YieldKeyword */, 41 /* SyntaxKind.AsteriskToken */], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBetweenReturnAndSemicolon", 105 /* SyntaxKind.ReturnKeyword */, 26 /* SyntaxKind.SemicolonToken */, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceAfterCertainKeywords", [113 /* SyntaxKind.VarKeyword */, 109 /* SyntaxKind.ThrowKeyword */, 103 /* SyntaxKind.NewKeyword */, 89 /* SyntaxKind.DeleteKeyword */, 105 /* SyntaxKind.ReturnKeyword */, 112 /* SyntaxKind.TypeOfKeyword */, 132 /* SyntaxKind.AwaitKeyword */], anyToken, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterLetConstInVariableDeclaration", [119 /* SyntaxKind.LetKeyword */, 85 /* SyntaxKind.ConstKeyword */], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, 20 /* SyntaxKind.OpenParenToken */, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], 16 /* RuleAction.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 /* RuleAction.InsertSpace */), rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterVoidOperator", 114 /* SyntaxKind.VoidKeyword */, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], 4 /* RuleAction.InsertSpace */), // Async-await rule("SpaceBetweenAsyncAndOpenParen", 131 /* SyntaxKind.AsyncKeyword */, 20 /* SyntaxKind.OpenParenToken */, [isArrowFunctionContext, isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBetweenAsyncAndFunctionKeyword", 131 /* SyntaxKind.AsyncKeyword */, [98 /* SyntaxKind.FunctionKeyword */, 79 /* SyntaxKind.Identifier */], [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), // Template string rule("NoSpaceBetweenTagAndTemplateString", [79 /* SyntaxKind.Identifier */, 21 /* SyntaxKind.CloseParenToken */], [14 /* SyntaxKind.NoSubstitutionTemplateLiteral */, 15 /* SyntaxKind.TemplateHead */], [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // JSX opening elements rule("SpaceBeforeJsxAttribute", anyToken, 79 /* SyntaxKind.Identifier */, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, 43 /* SyntaxKind.SlashToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", 43 /* SyntaxKind.SlashToken */, 31 /* SyntaxKind.GreaterThanToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, 63 /* SyntaxKind.EqualsToken */, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterEqualInJsxAttribute", 63 /* SyntaxKind.EqualsToken */, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // TypeScript-specific rules // Use of module as a function call. e.g.: import m2 = module("m2"); rule("NoSpaceAfterModuleImport", [141 /* SyntaxKind.ModuleKeyword */, 146 /* SyntaxKind.RequireKeyword */], 20 /* SyntaxKind.OpenParenToken */, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // Add a space around certain TypeScript keywords rule("SpaceAfterCertainTypeScriptKeywords", [ 126 /* SyntaxKind.AbstractKeyword */, 84 /* SyntaxKind.ClassKeyword */, 135 /* SyntaxKind.DeclareKeyword */, 88 /* SyntaxKind.DefaultKeyword */, 92 /* SyntaxKind.EnumKeyword */, 93 /* SyntaxKind.ExportKeyword */, 94 /* SyntaxKind.ExtendsKeyword */, 136 /* SyntaxKind.GetKeyword */, 117 /* SyntaxKind.ImplementsKeyword */, 100 /* SyntaxKind.ImportKeyword */, 118 /* SyntaxKind.InterfaceKeyword */, 141 /* SyntaxKind.ModuleKeyword */, 142 /* SyntaxKind.NamespaceKeyword */, 121 /* SyntaxKind.PrivateKeyword */, 123 /* SyntaxKind.PublicKeyword */, 122 /* SyntaxKind.ProtectedKeyword */, 145 /* SyntaxKind.ReadonlyKeyword */, 149 /* SyntaxKind.SetKeyword */, 124 /* SyntaxKind.StaticKeyword */, 152 /* SyntaxKind.TypeKeyword */, 156 /* SyntaxKind.FromKeyword */, 140 /* SyntaxKind.KeyOfKeyword */, 137 /* SyntaxKind.InferKeyword */, ], anyToken, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBeforeCertainTypeScriptKeywords", anyToken, [94 /* SyntaxKind.ExtendsKeyword */, 117 /* SyntaxKind.ImplementsKeyword */, 156 /* SyntaxKind.FromKeyword */], [isNonJsxSameLineTokenContext], 4 /* RuleAction.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 /* SyntaxKind.StringLiteral */, 18 /* SyntaxKind.OpenBraceToken */, [isModuleDeclContext], 4 /* RuleAction.InsertSpace */), // Lambda expressions rule("SpaceBeforeArrow", anyToken, 38 /* SyntaxKind.EqualsGreaterThanToken */, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterArrow", 38 /* SyntaxKind.EqualsGreaterThanToken */, anyToken, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), // Optional parameters and let args rule("NoSpaceAfterEllipsis", 25 /* SyntaxKind.DotDotDotToken */, 79 /* SyntaxKind.Identifier */, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterOptionalParameters", 57 /* SyntaxKind.QuestionToken */, [21 /* SyntaxKind.CloseParenToken */, 27 /* SyntaxKind.CommaToken */], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 16 /* RuleAction.DeleteSpace */), // Remove spaces in empty interface literals. e.g.: x: {} rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", 18 /* SyntaxKind.OpenBraceToken */, 19 /* SyntaxKind.CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectTypeContext], 16 /* RuleAction.DeleteSpace */), // generics and type assertions rule("NoSpaceBeforeOpenAngularBracket", typeNames, 29 /* SyntaxKind.LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBetweenCloseParenAndAngularBracket", 21 /* SyntaxKind.CloseParenToken */, 29 /* SyntaxKind.LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterOpenAngularBracket", 29 /* SyntaxKind.LessThanToken */, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeCloseAngularBracket", anyToken, 31 /* SyntaxKind.GreaterThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterCloseAngularBracket", 31 /* SyntaxKind.GreaterThanToken */, [20 /* SyntaxKind.OpenParenToken */, 22 /* SyntaxKind.OpenBracketToken */, 31 /* SyntaxKind.GreaterThanToken */, 27 /* SyntaxKind.CommaToken */], [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext /*To prevent an interference with the SpaceBeforeOpenParenInFuncDecl rule*/], 16 /* RuleAction.DeleteSpace */), // decorators rule("SpaceBeforeAt", [21 /* SyntaxKind.CloseParenToken */, 79 /* SyntaxKind.Identifier */], 59 /* SyntaxKind.AtToken */, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterAt", 59 /* SyntaxKind.AtToken */, anyToken, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // Insert space after @ in decorator rule("SpaceAfterDecorator", anyToken, [ 126 /* SyntaxKind.AbstractKeyword */, 79 /* SyntaxKind.Identifier */, 93 /* SyntaxKind.ExportKeyword */, 88 /* SyntaxKind.DefaultKeyword */, 84 /* SyntaxKind.ClassKeyword */, 124 /* SyntaxKind.StaticKeyword */, 123 /* SyntaxKind.PublicKeyword */, 121 /* SyntaxKind.PrivateKeyword */, 122 /* SyntaxKind.ProtectedKeyword */, 136 /* SyntaxKind.GetKeyword */, 149 /* SyntaxKind.SetKeyword */, 22 /* SyntaxKind.OpenBracketToken */, 41 /* SyntaxKind.AsteriskToken */, ], [isEndOfDecoratorContextOnSameLine], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, 53 /* SyntaxKind.ExclamationToken */, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterNewKeywordOnConstructorSignature", 103 /* SyntaxKind.NewKeyword */, 20 /* SyntaxKind.OpenParenToken */, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceLessThanAndNonJSXTypeAnnotation", 29 /* SyntaxKind.LessThanToken */, 29 /* SyntaxKind.LessThanToken */, [isNonJsxSameLineTokenContext], 4 /* RuleAction.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", 134 /* SyntaxKind.ConstructorKeyword */, 20 /* SyntaxKind.OpenParenToken */, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterConstructor", 134 /* SyntaxKind.ConstructorKeyword */, 20 /* SyntaxKind.OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceAfterComma", 27 /* SyntaxKind.CommaToken */, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket, isNextTokenNotCloseParen], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterComma", 27 /* SyntaxKind.CommaToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], 16 /* RuleAction.DeleteSpace */), // Insert space after function keyword for anonymous functions rule("SpaceAfterAnonymousFunctionKeyword", [98 /* SyntaxKind.FunctionKeyword */, 41 /* SyntaxKind.AsteriskToken */], 20 /* SyntaxKind.OpenParenToken */, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterAnonymousFunctionKeyword", [98 /* SyntaxKind.FunctionKeyword */, 41 /* SyntaxKind.AsteriskToken */], 20 /* SyntaxKind.OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 16 /* RuleAction.DeleteSpace */), // Insert space after keywords in control flow statements rule("SpaceAfterKeywordInControl", keywords, 20 /* SyntaxKind.OpenParenToken */, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterKeywordInControl", keywords, 20 /* SyntaxKind.OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 16 /* RuleAction.DeleteSpace */), // Insert space after opening and before closing nonempty parenthesis rule("SpaceAfterOpenParen", 20 /* SyntaxKind.OpenParenToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBeforeCloseParen", anyToken, 21 /* SyntaxKind.CloseParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBetweenOpenParens", 20 /* SyntaxKind.OpenParenToken */, 20 /* SyntaxKind.OpenParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBetweenParens", 20 /* SyntaxKind.OpenParenToken */, 21 /* SyntaxKind.CloseParenToken */, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterOpenParen", 20 /* SyntaxKind.OpenParenToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeCloseParen", anyToken, 21 /* SyntaxKind.CloseParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // Insert space after opening and before closing nonempty brackets rule("SpaceAfterOpenBracket", 22 /* SyntaxKind.OpenBracketToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBeforeCloseBracket", anyToken, 23 /* SyntaxKind.CloseBracketToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBetweenBrackets", 22 /* SyntaxKind.OpenBracketToken */, 23 /* SyntaxKind.CloseBracketToken */, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterOpenBracket", 22 /* SyntaxKind.OpenBracketToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeCloseBracket", anyToken, 23 /* SyntaxKind.CloseBracketToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. rule("SpaceAfterOpenBrace", 18 /* SyntaxKind.OpenBraceToken */, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBeforeCloseBrace", anyToken, 19 /* SyntaxKind.CloseBraceToken */, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBetweenEmptyBraceBrackets", 18 /* SyntaxKind.OpenBraceToken */, 19 /* SyntaxKind.CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterOpenBrace", 18 /* SyntaxKind.OpenBraceToken */, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeCloseBrace", anyToken, 19 /* SyntaxKind.CloseBraceToken */, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // Insert a space after opening and before closing empty brace brackets rule("SpaceBetweenEmptyBraceBrackets", 18 /* SyntaxKind.OpenBraceToken */, 19 /* SyntaxKind.CloseBraceToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces")], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBetweenEmptyBraceBrackets", 18 /* SyntaxKind.OpenBraceToken */, 19 /* SyntaxKind.CloseBraceToken */, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // Insert space after opening and before closing template string braces rule("SpaceAfterTemplateHeadAndMiddle", [15 /* SyntaxKind.TemplateHead */, 16 /* SyntaxKind.TemplateMiddle */], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], 4 /* RuleAction.InsertSpace */, 1 /* RuleFlags.CanDeleteNewLines */), rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [16 /* SyntaxKind.TemplateMiddle */, 17 /* SyntaxKind.TemplateTail */], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterTemplateHeadAndMiddle", [15 /* SyntaxKind.TemplateHead */, 16 /* SyntaxKind.TemplateMiddle */], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], 16 /* RuleAction.DeleteSpace */, 1 /* RuleFlags.CanDeleteNewLines */), rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [16 /* SyntaxKind.TemplateMiddle */, 17 /* SyntaxKind.TemplateTail */], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // No space after { and before } in JSX expression rule("SpaceAfterOpenBraceInJsxExpression", 18 /* SyntaxKind.OpenBraceToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 4 /* RuleAction.InsertSpace */), rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, 19 /* SyntaxKind.CloseBraceToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterOpenBraceInJsxExpression", 18 /* SyntaxKind.OpenBraceToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, 19 /* SyntaxKind.CloseBraceToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 16 /* RuleAction.DeleteSpace */), // Insert space after semicolon in for statement rule("SpaceAfterSemicolonInFor", 26 /* SyntaxKind.SemicolonToken */, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterSemicolonInFor", 26 /* SyntaxKind.SemicolonToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 16 /* RuleAction.DeleteSpace */), // Insert space before and after binary operators rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceBeforeOpenParenInFuncDecl", anyToken, 20 /* SyntaxKind.OpenParenToken */, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, 20 /* SyntaxKind.OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 16 /* RuleAction.DeleteSpace */), // Open Brace braces after control block rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 18 /* SyntaxKind.OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], 8 /* RuleAction.InsertNewLine */, 1 /* RuleFlags.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 /* SyntaxKind.OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], 8 /* RuleAction.InsertNewLine */, 1 /* RuleFlags.CanDeleteNewLines */), // Open Brace braces after TypeScript module/class/interface rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 18 /* SyntaxKind.OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], 8 /* RuleAction.InsertNewLine */, 1 /* RuleFlags.CanDeleteNewLines */), rule("SpaceAfterTypeAssertion", 31 /* SyntaxKind.GreaterThanToken */, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceAfterTypeAssertion", 31 /* SyntaxKind.GreaterThanToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceBeforeTypeAnnotation", anyToken, [57 /* SyntaxKind.QuestionToken */, 58 /* SyntaxKind.ColonToken */], [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 4 /* RuleAction.InsertSpace */), rule("NoSpaceBeforeTypeAnnotation", anyToken, [57 /* SyntaxKind.QuestionToken */, 58 /* SyntaxKind.ColonToken */], [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 16 /* RuleAction.DeleteSpace */), rule("NoOptionalSemicolon", 26 /* SyntaxKind.SemicolonToken */, anyTokenIncludingEOF, [optionEquals("semicolons", ts.SemicolonPreference.Remove), isSemicolonDeletionContext], 32 /* RuleAction.DeleteToken */), rule("OptionalSemicolon", anyToken, anyTokenIncludingEOF, [optionEquals("semicolons", ts.SemicolonPreference.Insert), isSemicolonInsertionContext], 64 /* RuleAction.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 /* SyntaxKind.SemicolonToken */, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 18 /* SyntaxKind.OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 4 /* RuleAction.InsertSpace */, 1 /* RuleFlags.CanDeleteNewLines */), rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 18 /* SyntaxKind.OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 4 /* RuleAction.InsertSpace */, 1 /* RuleFlags.CanDeleteNewLines */), rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 18 /* SyntaxKind.OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 4 /* RuleAction.InsertSpace */, 1 /* RuleFlags.CanDeleteNewLines */), rule("NoSpaceBeforeComma", anyToken, 27 /* SyntaxKind.CommaToken */, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), // No space before and after indexer `x[]` rule("NoSpaceBeforeOpenBracket", anyTokenExcept(131 /* SyntaxKind.AsyncKeyword */, 82 /* SyntaxKind.CaseKeyword */), 22 /* SyntaxKind.OpenBracketToken */, [isNonJsxSameLineTokenContext], 16 /* RuleAction.DeleteSpace */), rule("NoSpaceAfterCloseBracket", 23 /* SyntaxKind.CloseBracketToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], 16 /* RuleAction.DeleteSpace */), rule("SpaceAfterSemicolon", 26 /* SyntaxKind.SemicolonToken */, anyToken, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), // Remove extra space between for and await rule("SpaceBetweenForAndAwaitKeyword", 97 /* SyntaxKind.ForKeyword */, 132 /* SyntaxKind.AwaitKeyword */, [isNonJsxSameLineTokenContext], 4 /* RuleAction.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 /* SyntaxKind.CloseParenToken */, 90 /* SyntaxKind.DoKeyword */, 91 /* SyntaxKind.ElseKeyword */, 82 /* SyntaxKind.CaseKeyword */], anyToken, [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], 4 /* RuleAction.InsertSpace */), // This low-pri rule takes care of "try {", "catch {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. rule("SpaceAfterTryCatchFinally", [111 /* SyntaxKind.TryKeyword */, 83 /* SyntaxKind.CatchKeyword */, 96 /* SyntaxKind.FinallyKeyword */], 18 /* SyntaxKind.OpenBraceToken */, [isNonJsxSameLineTokenContext], 4 /* RuleAction.InsertSpace */), ]; return __spreadArray(__spreadArray(__spreadArray([], highPriorityCommonRules, true), userConfigurableRules, true), lowPriorityCommonRules, true); } 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 /* RuleFlags.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 === 242 /* SyntaxKind.ForStatement */; } function isNotForContext(context) { return !isForContext(context); } function isBinaryOpContext(context) { switch (context.contextNode.kind) { case 221 /* SyntaxKind.BinaryExpression */: return context.contextNode.operatorToken.kind !== 27 /* SyntaxKind.CommaToken */; case 222 /* SyntaxKind.ConditionalExpression */: case 189 /* SyntaxKind.ConditionalType */: case 229 /* SyntaxKind.AsExpression */: case 275 /* SyntaxKind.ExportSpecifier */: case 270 /* SyntaxKind.ImportSpecifier */: case 177 /* SyntaxKind.TypePredicate */: case 187 /* SyntaxKind.UnionType */: case 188 /* SyntaxKind.IntersectionType */: return true; // equals in binding elements: function foo([[x, y] = [1, 2]]) case 203 /* SyntaxKind.BindingElement */: // equals in type X = ... // falls through case 259 /* SyntaxKind.TypeAliasDeclaration */: // equal in import a = module('a'); // falls through case 265 /* SyntaxKind.ImportEqualsDeclaration */: // equal in export = 1 // falls through case 271 /* SyntaxKind.ExportAssignment */: // equal in let a = 0 // falls through case 254 /* SyntaxKind.VariableDeclaration */: // equal in p = 0 // falls through case 164 /* SyntaxKind.Parameter */: case 299 /* SyntaxKind.EnumMember */: case 167 /* SyntaxKind.PropertyDeclaration */: case 166 /* SyntaxKind.PropertySignature */: return context.currentTokenSpan.kind === 63 /* SyntaxKind.EqualsToken */ || context.nextTokenSpan.kind === 63 /* SyntaxKind.EqualsToken */; // "in" keyword in for (let x in []) { } case 243 /* SyntaxKind.ForInStatement */: // "in" keyword in [P in keyof T]: T[P] // falls through case 163 /* SyntaxKind.TypeParameter */: return context.currentTokenSpan.kind === 101 /* SyntaxKind.InKeyword */ || context.nextTokenSpan.kind === 101 /* SyntaxKind.InKeyword */ || context.currentTokenSpan.kind === 63 /* SyntaxKind.EqualsToken */ || context.nextTokenSpan.kind === 63 /* SyntaxKind.EqualsToken */; // Technically, "of" is not a binary operator, but format it the same way as "in" case 244 /* SyntaxKind.ForOfStatement */: return context.currentTokenSpan.kind === 160 /* SyntaxKind.OfKeyword */ || context.nextTokenSpan.kind === 160 /* SyntaxKind.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 === 167 /* SyntaxKind.PropertyDeclaration */ || contextKind === 166 /* SyntaxKind.PropertySignature */ || contextKind === 164 /* SyntaxKind.Parameter */ || contextKind === 254 /* SyntaxKind.VariableDeclaration */ || ts.isFunctionLikeKind(contextKind); } function isConditionalOperatorContext(context) { return context.contextNode.kind === 222 /* SyntaxKind.ConditionalExpression */ || context.contextNode.kind === 189 /* SyntaxKind.ConditionalType */; } function isSameLineTokenOrBeforeBlockContext(context) { return context.TokensAreOnSameLine() || isBeforeBlockContext(context); } function isBraceWrappedContext(context) { return context.contextNode.kind === 201 /* SyntaxKind.ObjectBindingPattern */ || context.contextNode.kind === 195 /* SyntaxKind.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 235 /* SyntaxKind.Block */: case 263 /* SyntaxKind.CaseBlock */: case 205 /* SyntaxKind.ObjectLiteralExpression */: case 262 /* SyntaxKind.ModuleBlock */: return true; } return false; } function isFunctionDeclContext(context) { switch (context.contextNode.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: // case SyntaxKind.MemberFunctionDeclaration: // falls through case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: // case SyntaxKind.MethodSignature: // falls through case 174 /* SyntaxKind.CallSignature */: case 213 /* SyntaxKind.FunctionExpression */: case 171 /* SyntaxKind.Constructor */: case 214 /* SyntaxKind.ArrowFunction */: // case SyntaxKind.ConstructorDeclaration: // case SyntaxKind.SimpleArrowFunctionExpression: // case SyntaxKind.ParenthesizedArrowFunctionExpression: // falls through case 258 /* SyntaxKind.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 === 256 /* SyntaxKind.FunctionDeclaration */ || context.contextNode.kind === 213 /* SyntaxKind.FunctionExpression */; } function isTypeScriptDeclWithBlockContext(context) { return nodeIsTypeScriptDeclWithBlockContext(context.contextNode); } function nodeIsTypeScriptDeclWithBlockContext(node) { switch (node.kind) { case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 182 /* SyntaxKind.TypeLiteral */: case 261 /* SyntaxKind.ModuleDeclaration */: case 272 /* SyntaxKind.ExportDeclaration */: case 273 /* SyntaxKind.NamedExports */: case 266 /* SyntaxKind.ImportDeclaration */: case 269 /* SyntaxKind.NamedImports */: return true; } return false; } function isAfterCodeBlockContext(context) { switch (context.currentTokenParent.kind) { case 257 /* SyntaxKind.ClassDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 292 /* SyntaxKind.CatchClause */: case 262 /* SyntaxKind.ModuleBlock */: case 249 /* SyntaxKind.SwitchStatement */: return true; case 235 /* SyntaxKind.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 !== 214 /* SyntaxKind.ArrowFunction */ && blockParent.kind !== 213 /* SyntaxKind.FunctionExpression */) { return true; } } } return false; } function isControlDeclContext(context) { switch (context.contextNode.kind) { case 239 /* SyntaxKind.IfStatement */: case 249 /* SyntaxKind.SwitchStatement */: case 242 /* SyntaxKind.ForStatement */: case 243 /* SyntaxKind.ForInStatement */: case 244 /* SyntaxKind.ForOfStatement */: case 241 /* SyntaxKind.WhileStatement */: case 252 /* SyntaxKind.TryStatement */: case 240 /* SyntaxKind.DoStatement */: case 248 /* SyntaxKind.WithStatement */: // TODO // case SyntaxKind.ElseClause: // falls through case 292 /* SyntaxKind.CatchClause */: return true; default: return false; } } function isObjectContext(context) { return context.contextNode.kind === 205 /* SyntaxKind.ObjectLiteralExpression */; } function isFunctionCallContext(context) { return context.contextNode.kind === 208 /* SyntaxKind.CallExpression */; } function isNewContext(context) { return context.contextNode.kind === 209 /* SyntaxKind.NewExpression */; } function isFunctionCallOrNewContext(context) { return isFunctionCallContext(context) || isNewContext(context); } function isPreviousTokenNotComma(context) { return context.currentTokenSpan.kind !== 27 /* SyntaxKind.CommaToken */; } function isNextTokenNotCloseBracket(context) { return context.nextTokenSpan.kind !== 23 /* SyntaxKind.CloseBracketToken */; } function isNextTokenNotCloseParen(context) { return context.nextTokenSpan.kind !== 21 /* SyntaxKind.CloseParenToken */; } function isArrowFunctionContext(context) { return context.contextNode.kind === 214 /* SyntaxKind.ArrowFunction */; } function isImportTypeContext(context) { return context.contextNode.kind === 200 /* SyntaxKind.ImportType */; } function isNonJsxSameLineTokenContext(context) { return context.TokensAreOnSameLine() && context.contextNode.kind !== 11 /* SyntaxKind.JsxText */; } function isNonJsxTextContext(context) { return context.contextNode.kind !== 11 /* SyntaxKind.JsxText */; } function isNonJsxElementOrFragmentContext(context) { return context.contextNode.kind !== 278 /* SyntaxKind.JsxElement */ && context.contextNode.kind !== 282 /* SyntaxKind.JsxFragment */; } function isJsxExpressionContext(context) { return context.contextNode.kind === 288 /* SyntaxKind.JsxExpression */ || context.contextNode.kind === 287 /* SyntaxKind.JsxSpreadAttribute */; } function isNextTokenParentJsxAttribute(context) { return context.nextTokenParent.kind === 285 /* SyntaxKind.JsxAttribute */; } function isJsxAttributeContext(context) { return context.contextNode.kind === 285 /* SyntaxKind.JsxAttribute */; } function isJsxSelfClosingElementContext(context) { return context.contextNode.kind === 279 /* SyntaxKind.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 === 165 /* SyntaxKind.Decorator */; } function isStartOfVariableDeclarationList(context) { return context.currentTokenParent.kind === 255 /* SyntaxKind.VariableDeclarationList */ && context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; } function isNotFormatOnEnter(context) { return context.formattingRequestKind !== 2 /* FormattingRequestKind.FormatOnEnter */; } function isModuleDeclContext(context) { return context.contextNode.kind === 261 /* SyntaxKind.ModuleDeclaration */; } function isObjectTypeContext(context) { return context.contextNode.kind === 182 /* SyntaxKind.TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; } function isConstructorSignatureContext(context) { return context.contextNode.kind === 175 /* SyntaxKind.ConstructSignature */; } function isTypeArgumentOrParameterOrAssertion(token, parent) { if (token.kind !== 29 /* SyntaxKind.LessThanToken */ && token.kind !== 31 /* SyntaxKind.GreaterThanToken */) { return false; } switch (parent.kind) { case 178 /* SyntaxKind.TypeReference */: case 211 /* SyntaxKind.TypeAssertionExpression */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: case 174 /* SyntaxKind.CallSignature */: case 175 /* SyntaxKind.ConstructSignature */: case 208 /* SyntaxKind.CallExpression */: case 209 /* SyntaxKind.NewExpression */: case 228 /* SyntaxKind.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 === 211 /* SyntaxKind.TypeAssertionExpression */; } function isVoidOpContext(context) { return context.currentTokenSpan.kind === 114 /* SyntaxKind.VoidKeyword */ && context.currentTokenParent.kind === 217 /* SyntaxKind.VoidExpression */; } function isYieldOrYieldStarWithOperand(context) { return context.contextNode.kind === 224 /* SyntaxKind.YieldExpression */ && context.contextNode.expression !== undefined; } function isNonNullAssertionContext(context) { return context.contextNode.kind === 230 /* SyntaxKind.NonNullExpression */; } function isNotStatementConditionContext(context) { return !isStatementConditionContext(context); } function isStatementConditionContext(context) { switch (context.contextNode.kind) { case 239 /* SyntaxKind.IfStatement */: case 242 /* SyntaxKind.ForStatement */: case 243 /* SyntaxKind.ForInStatement */: case 244 /* SyntaxKind.ForOfStatement */: case 240 /* SyntaxKind.DoStatement */: case 241 /* SyntaxKind.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 /* SyntaxKind.CloseBraceToken */ || nextTokenKind === 1 /* SyntaxKind.EndOfFileToken */; } if (nextTokenKind === 234 /* SyntaxKind.SemicolonClassElement */ || nextTokenKind === 26 /* SyntaxKind.SemicolonToken */) { return false; } if (context.contextNode.kind === 258 /* SyntaxKind.InterfaceDeclaration */ || context.contextNode.kind === 259 /* SyntaxKind.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 /* SyntaxKind.OpenParenToken */; } if (ts.isPropertyDeclaration(context.currentTokenParent)) { return !context.currentTokenParent.initializer; } return context.currentTokenParent.kind !== 242 /* SyntaxKind.ForStatement */ && context.currentTokenParent.kind !== 236 /* SyntaxKind.EmptyStatement */ && context.currentTokenParent.kind !== 234 /* SyntaxKind.SemicolonClassElement */ && nextTokenKind !== 22 /* SyntaxKind.OpenBracketToken */ && nextTokenKind !== 20 /* SyntaxKind.OpenParenToken */ && nextTokenKind !== 39 /* SyntaxKind.PlusToken */ && nextTokenKind !== 40 /* SyntaxKind.MinusToken */ && nextTokenKind !== 43 /* SyntaxKind.SlashToken */ && nextTokenKind !== 13 /* SyntaxKind.RegularExpressionLiteral */ && nextTokenKind !== 27 /* SyntaxKind.CommaToken */ && nextTokenKind !== 223 /* SyntaxKind.TemplateExpression */ && nextTokenKind !== 15 /* SyntaxKind.TemplateHead */ && nextTokenKind !== 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */ && nextTokenKind !== 24 /* SyntaxKind.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 /* RuleAction.StopProcessingSpaceActions */) { mask |= 28 /* RuleAction.ModifySpaceAction */; } if (ruleAction & 2 /* RuleAction.StopProcessingTokenActions */) { mask |= 96 /* RuleAction.ModifyTokenAction */; } if (ruleAction & 28 /* RuleAction.ModifySpaceAction */) { mask |= 28 /* RuleAction.ModifySpaceAction */; } if (ruleAction & 96 /* RuleAction.ModifyTokenAction */) { mask |= 96 /* RuleAction.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 <= 160 /* SyntaxKind.LastKeyword */ && column <= 160 /* SyntaxKind.LastKeyword */, "Must compute formatting context from tokens"); return (row * mapRowLength) + column; } var maskBitSize = 5; var mask = 31; // MaskBitSize bits var mapRowLength = 160 /* SyntaxKind.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 /* RuleAction.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 /* FormattingRequestKind.FormatOnEnter */); } formatting.formatOnEnter = formatOnEnter; function formatOnSemicolon(position, sourceFile, formatContext) { var semicolon = findImmediatelyPrecedingTokenOfKind(position, 26 /* SyntaxKind.SemicolonToken */, sourceFile); return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, 3 /* FormattingRequestKind.FormatOnSemicolon */); } formatting.formatOnSemicolon = formatOnSemicolon; function formatOnOpeningCurly(position, sourceFile, formatContext) { var openingCurly = findImmediatelyPrecedingTokenOfKind(position, 18 /* SyntaxKind.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 /* FormattingRequestKind.FormatOnOpeningCurlyBrace */); } formatting.formatOnOpeningCurly = formatOnOpeningCurly; function formatOnClosingCurly(position, sourceFile, formatContext) { var precedingToken = findImmediatelyPrecedingTokenOfKind(position, 19 /* SyntaxKind.CloseBraceToken */, sourceFile); return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, 5 /* FormattingRequestKind.FormatOnClosingCurlyBrace */); } formatting.formatOnClosingCurly = formatOnClosingCurly; function formatDocument(sourceFile, formatContext) { var span = { pos: 0, end: sourceFile.text.length }; return formatSpan(span, sourceFile, formatContext, 0 /* FormattingRequestKind.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 /* FormattingRequestKind.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 257 /* SyntaxKind.ClassDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: return ts.rangeContainsRange(parent.members, node); case 261 /* SyntaxKind.ModuleDeclaration */: var body = parent.body; return !!body && body.kind === 262 /* SyntaxKind.ModuleBlock */ && ts.rangeContainsRange(body.statements, node); case 305 /* SyntaxKind.SourceFile */: case 235 /* SyntaxKind.Block */: case 262 /* SyntaxKind.ModuleBlock */: return ts.rangeContainsRange(parent.statements, node); case 292 /* SyntaxKind.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 /* Constants.Unknown */; var child; while (n) { var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; if (previousLine !== -1 /* Constants.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: node.pos, end: node.end }; return formatting.getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, function (scanner) { return formatSpanWorker(range, node, initialIndentation, delta, scanner, formatContext, 1 /* FormattingRequestKind.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 _b; 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 /* Constants.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 indentation = formatting.SmartIndenter.nodeWillIndentChild(options, enclosingNode, /*child*/ undefined, sourceFile, /*indentByDefault*/ false) ? initialIndentation + options.indentSize : initialIndentation; var leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); if (leadingTrivia) { indentTriviaItems(leadingTrivia, indentation, /*indentNextTokenOrTrivia*/ false, function (item) { return processRange(item, sourceFile.getLineAndCharacterOfPosition(item.pos), enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined); }); if (options.trimTrailingWhitespace !== false) { trimTrailingWhitespacesForRemainingRange(leadingTrivia); } } } if (previousRange && formattingScanner.getStartPos() >= originalRange.end) { var tokenInfo = formattingScanner.isOnEOF() ? formattingScanner.readEOFTokenRange() : formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(enclosingNode).token : undefined; if (tokenInfo) { var parent = ((_b = ts.findPrecedingToken(tokenInfo.end, sourceFile, enclosingNode)) === null || _b === void 0 ? void 0 : _b.parent) || previousParent; processPair(tokenInfo, sourceFile.getLineAndCharacterOfPosition(tokenInfo.pos).line, parent, previousRange, previousRangeStartLine, previousParent, parent, /*dynamicIndentation*/ undefined); } } 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 /* Constants.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 /* Constants.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 /* Constants.Unknown */) { if (node.kind === 20 /* SyntaxKind.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) || formatting.SmartIndenter.childIsUnindentedBranchOfConditionalExpression(parent, node, startLine, sourceFile) || 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 257 /* SyntaxKind.ClassDeclaration */: return 84 /* SyntaxKind.ClassKeyword */; case 258 /* SyntaxKind.InterfaceDeclaration */: return 118 /* SyntaxKind.InterfaceKeyword */; case 256 /* SyntaxKind.FunctionDeclaration */: return 98 /* SyntaxKind.FunctionKeyword */; case 260 /* SyntaxKind.EnumDeclaration */: return 260 /* SyntaxKind.EnumDeclaration */; case 172 /* SyntaxKind.GetAccessor */: return 136 /* SyntaxKind.GetKeyword */; case 173 /* SyntaxKind.SetAccessor */: return 149 /* SyntaxKind.SetKeyword */; case 169 /* SyntaxKind.MethodDeclaration */: if (node.asteriskToken) { return 41 /* SyntaxKind.AsteriskToken */; } // falls through case 167 /* SyntaxKind.PropertyDeclaration */: case 164 /* SyntaxKind.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 /* SyntaxKind.CloseBraceToken */: case 23 /* SyntaxKind.CloseBracketToken */: case 21 /* SyntaxKind.CloseParenToken */: return indentation + getDelta(container); } return tokenIndentation !== -1 /* Constants.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 /* SyntaxKind.OpenBraceToken */: case 19 /* SyntaxKind.CloseBraceToken */: case 21 /* SyntaxKind.CloseParenToken */: case 91 /* SyntaxKind.ElseKeyword */: case 115 /* SyntaxKind.WhileKeyword */: case 59 /* SyntaxKind.AtToken */: return false; case 43 /* SyntaxKind.SlashToken */: case 31 /* SyntaxKind.GreaterThanToken */: switch (container.kind) { case 280 /* SyntaxKind.JsxOpeningElement */: case 281 /* SyntaxKind.JsxClosingElement */: case 279 /* SyntaxKind.JsxSelfClosingElement */: case 228 /* SyntaxKind.ExpressionWithTypeArguments */: return false; } break; case 22 /* SyntaxKind.OpenBracketToken */: case 23 /* SyntaxKind.CloseBracketToken */: if (container.kind !== 195 /* SyntaxKind.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 /* Constants.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() && formattingScanner.getStartPos() < originalRange.end) { var tokenInfo = formattingScanner.readTokenInfo(node); if (tokenInfo.token.end > Math.min(node.end, originalRange.end)) { break; } consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation, node); } function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem, isFirstListItem) { if (ts.nodeIsMissing(child)) { return inheritedIndentation; } 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 /* Constants.Unknown */; if (isListItem && ts.rangeContainsRange(originalRange, parent)) { childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); if (childIndentationAmount !== -1 /* Constants.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() && formattingScanner.getStartPos() < originalRange.end) { // proceed any parent tokens that are located prior to child.getStart() var tokenInfo = formattingScanner.readTokenInfo(node); if (tokenInfo.token.end > originalRange.end) { return inheritedIndentation; } if (tokenInfo.token.end > childStartPos) { if (tokenInfo.token.pos > childStartPos) { formattingScanner.skipToStartOf(child); } // stop when formatting scanner advances past the beginning of the child break; } consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, node); } if (!formattingScanner.isOnToken() || formattingScanner.getStartPos() >= originalRange.end) { return inheritedIndentation; } if (ts.isToken(child)) { // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules var tokenInfo = formattingScanner.readTokenInfo(child); // JSX text shouldn't affect indenting if (child.kind !== 11 /* SyntaxKind.JsxText */) { ts.Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); return inheritedIndentation; } } var effectiveParentStartLine = child.kind === 165 /* SyntaxKind.Decorator */ ? childStartLine : undecoratedParentStartLine; var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); childContextNode = node; if (isFirstListItem && parent.kind === 204 /* SyntaxKind.ArrayLiteralExpression */ && inheritedIndentation === -1 /* Constants.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; // node range is outside the target range - do not dive inside if (!ts.rangeOverlapsWithStartEnd(originalRange, nodes.pos, nodes.end)) { if (nodes.end < originalRange.pos) { formattingScanner.skipToEndOf(nodes); } return; } if (listStartToken !== 0 /* SyntaxKind.Unknown */) { // introduce a new indentation scope for lists (including list start and end tokens) while (formattingScanner.isOnToken() && formattingScanner.getStartPos() < originalRange.end) { 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 /* Constants.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 /* Constants.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 /* SyntaxKind.Unknown */ && formattingScanner.isOnToken() && formattingScanner.getStartPos() < originalRange.end) { var tokenInfo = formattingScanner.readTokenInfo(parent); if (tokenInfo.token.kind === 27 /* SyntaxKind.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 /* LineAction.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 /* LineAction.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 /* LineAction.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 /* Constants.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 /* Constants.Unknown */ && indentNextTokenOrTrivia) { insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAction === 1 /* LineAction.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 /* SyntaxKind.MultiLineCommentTrivia */: if (triviaInRange) { indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); } indentNextTokenOrTrivia = false; break; case 2 /* SyntaxKind.SingleLineCommentTrivia */: if (indentNextTokenOrTrivia && triviaInRange) { indentSingleLine(triviaItem); } indentNextTokenOrTrivia = false; break; case 4 /* SyntaxKind.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 /* LineAction.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 /* LineAction.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); if (dynamicIndentation) { switch (lineAction) { case 2 /* LineAction.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 /* LineAction.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 /* LineAction.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 /* RuleAction.DeleteSpace */) && rule.flags !== 1 /* RuleFlags.CanDeleteNewLines */; }); } else { trimTrailingWhitespaces = trimTrailingWhitespaces && currentItem.kind !== 1 /* SyntaxKind.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 /* CharacterCodes.tab */) { column += options.tabSize - column % options.tabSize; } else { column++; } } return column; } function indentationIsDifferent(indentationString, startLinePosition) { return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length); } function indentMultilineComment(commentRange, indentation, firstLineIsIndented, indentFinalLine) { 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); 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); 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. * Exclude comments as they had been previously processed. */ function trimTrailingWhitespacesForRemainingRange(trivias) { var startPos = previousRange ? previousRange.end : originalRange.pos; for (var _i = 0, trivias_1 = trivias; _i < trivias_1.length; _i++) { var trivia = trivias_1[_i]; if (ts.isComment(trivia.kind)) { if (startPos < trivia.pos) { trimTrailingWitespacesForPositions(startPos, trivia.pos - 1, previousRange); } startPos = trivia.end + 1; } } if (startPos < originalRange.end) { trimTrailingWitespacesForPositions(startPos, originalRange.end, previousRange); } } function trimTrailingWitespacesForPositions(startPos, endPos, previousRange) { var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line; var endLine = sourceFile.getLineAndCharacterOfPosition(endPos).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 /* RuleAction.StopProcessingSpaceActions */: // no action required return 0 /* LineAction.None */; case 16 /* RuleAction.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 /* LineAction.LineRemoved */ : 0 /* LineAction.None */; } break; case 32 /* RuleAction.DeleteToken */: recordDelete(previousRange.pos, previousRange.end - previousRange.pos); break; case 8 /* RuleAction.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 /* RuleFlags.CanDeleteNewLines */ && previousStartLine !== currentStartLine) { return 0 /* LineAction.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 /* LineAction.None */ : 1 /* LineAction.LineAdded */; } break; case 4 /* RuleAction.InsertSpace */: // exit early if we on different lines and rule cannot change number of newlines if (rule.flags !== 1 /* RuleFlags.CanDeleteNewLines */ && previousStartLine !== currentStartLine) { return 0 /* LineAction.None */; } var posDelta = currentRange.pos - previousRange.end; if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* CharacterCodes.space */) { recordReplace(previousRange.end, currentRange.pos - previousRange.end, " "); return onLaterLine ? 2 /* LineAction.LineRemoved */ : 0 /* LineAction.None */; } break; case 64 /* RuleAction.InsertTrailingSemicolon */: recordInsert(previousRange.end, ";"); } return 0 /* LineAction.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 /* SyntaxKind.SingleLineCommentTrivia */ || position === sourceFile.getFullWidth()); }); } formatting.getRangeOfEnclosingComment = getRangeOfEnclosingComment; function getOpenTokenForList(node, list) { switch (node.kind) { case 171 /* SyntaxKind.Constructor */: case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: case 214 /* SyntaxKind.ArrowFunction */: if (node.typeParameters === list) { return 29 /* SyntaxKind.LessThanToken */; } else if (node.parameters === list) { return 20 /* SyntaxKind.OpenParenToken */; } break; case 208 /* SyntaxKind.CallExpression */: case 209 /* SyntaxKind.NewExpression */: if (node.typeArguments === list) { return 29 /* SyntaxKind.LessThanToken */; } else if (node.arguments === list) { return 20 /* SyntaxKind.OpenParenToken */; } break; case 178 /* SyntaxKind.TypeReference */: if (node.typeArguments === list) { return 29 /* SyntaxKind.LessThanToken */; } break; case 182 /* SyntaxKind.TypeLiteral */: return 18 /* SyntaxKind.OpenBraceToken */; } return 0 /* SyntaxKind.Unknown */; } function getCloseTokenForOpenToken(kind) { switch (kind) { case 20 /* SyntaxKind.OpenParenToken */: return 21 /* SyntaxKind.CloseParenToken */; case 29 /* SyntaxKind.LessThanToken */: return 31 /* SyntaxKind.GreaterThanToken */; case 18 /* SyntaxKind.OpenBraceToken */: return 19 /* SyntaxKind.CloseBraceToken */; } return 0 /* SyntaxKind.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 /* SyntaxKind.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. var currentToken = ts.getTokenAtPosition(sourceFile, position); // For object literals, we want indentation to work just like with blocks. // If the `{` starts in any position (even in the middle of a line), then // the following indentation should treat `{` as the start of that line (including leading whitespace). // ``` // const a: { x: undefined, y: undefined } = {} // leading 4 whitespaces and { starts in the middle of line // -> // const a: { x: undefined, y: undefined } = { // x: undefined, // y: undefined, // } // --------------------- // const a: {x : undefined, y: undefined } = // {} // -> // const a: { x: undefined, y: undefined } = // { // leading 5 whitespaces and { starts at 6 column // x: undefined, // y: undefined, // } // ``` var isObjectLiteral = currentToken.kind === 18 /* SyntaxKind.OpenBraceToken */ && currentToken.parent.kind === 205 /* SyntaxKind.ObjectLiteralExpression */; if (options.indentStyle === ts.IndentStyle.Block || isObjectLiteral) { return getBlockIndent(sourceFile, position, options); } if (precedingToken.kind === 27 /* SyntaxKind.CommaToken */ && precedingToken.parent.kind !== 221 /* SyntaxKind.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 /* Value.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)) { var useTheSameBaseIndentation = [213 /* SyntaxKind.FunctionExpression */, 214 /* SyntaxKind.ArrowFunction */].indexOf(currentToken.parent.kind) !== -1; var indentSize = useTheSameBaseIndentation ? 0 : options.indentSize; return getActualIndentationForListStartLine(containerList, sourceFile, 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 /* CharacterCodes.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 /* NextTokenKind.Unknown */ // handle cases when codefix is about to be inserted before the close brace ? assumeNewLineBeforeCloseBrace && nextTokenKind === 2 /* NextTokenKind.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 /* Value.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 _a; 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 firstListChild = (_a = getContainingList(current, sourceFile)) === null || _a === void 0 ? void 0 : _a[0]; // A list indents its children if the children begin on a later line than the list itself: // // f1( L0 - List start // { L1 - First child start: indented, along with all other children // prop: 0 // }, // { // prop: 1 // } // ) // // f2({ L0 - List start and first child start: children are not indented. // prop: 0 Object properties are indented only one level, because the list // }, { itself contributes nothing. // prop: 1 L3 - The indentation of the second object literal is best understood by // }) looking at the relationship between the list and *first* list item. var listIndentsChild = !!firstListChild && getStartLineAndCharacterForNode(firstListChild, sourceFile).line > containingListOrParentStart.line; var actualIndentation = getActualIndentationForListItem(current, sourceFile, options, listIndentsChild); if (actualIndentation !== -1 /* Value.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 /* Value.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 /* Value.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 === 305 /* SyntaxKind.SourceFile */ || !parentAndChildShareLine); if (!useActualIndentation) { return -1 /* Value.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 /* NextTokenKind.Unknown */; } if (nextToken.kind === 18 /* SyntaxKind.OpenBraceToken */) { // open braces are always indented at the parent level return 1 /* NextTokenKind.OpenBrace */; } else if (nextToken.kind === 19 /* SyntaxKind.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 /* NextTokenKind.CloseBrace */ : 0 /* NextTokenKind.Unknown */; } return 0 /* NextTokenKind.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 === 239 /* SyntaxKind.IfStatement */ && parent.elseStatement === child) { var elseKeyword = ts.findChildOfKind(parent, 91 /* SyntaxKind.ElseKeyword */, sourceFile); ts.Debug.assert(elseKeyword !== undefined); var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; return elseKeywordStartLine === childStartLine; } return false; } SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement; // A multiline conditional typically increases the indentation of its whenTrue and whenFalse children: // // condition // ? whenTrue // : whenFalse; // // However, that indentation does not apply if the subexpressions themselves span multiple lines, // applying their own indentation: // // (() => { // return complexCalculationForCondition(); // })() ? { // whenTrue: 'multiline object literal' // } : ( // whenFalse('multiline parenthesized expression') // ); // // In these cases, we must discard the indentation increase that would otherwise be applied to the // whenTrue and whenFalse children to avoid double-indenting their contents. To identify this scenario, // we check for the whenTrue branch beginning on the line that the condition ends, and the whenFalse // branch beginning on the line that the whenTrue branch ends. function childIsUnindentedBranchOfConditionalExpression(parent, child, childStartLine, sourceFile) { if (ts.isConditionalExpression(parent) && (child === parent.whenTrue || child === parent.whenFalse)) { var conditionEndLine = ts.getLineAndCharacterOfPosition(sourceFile, parent.condition.end).line; if (child === parent.whenTrue) { return childStartLine === conditionEndLine; } else { // On the whenFalse side, we have to look at the whenTrue side, because if that one was // indented, whenFalse must also be indented: // // const y = true // ? 1 : ( L1: whenTrue indented because it's on a new line // 0 L2: indented two stops, one because whenTrue was indented // ); and one because of the parentheses spanning multiple lines var trueStartLine = getStartLineAndCharacterForNode(parent.whenTrue, sourceFile).line; var trueEndLine = ts.getLineAndCharacterOfPosition(sourceFile, parent.whenTrue.end).line; return conditionEndLine === trueStartLine && trueEndLine === childStartLine; } } return false; } SmartIndenter.childIsUnindentedBranchOfConditionalExpression = childIsUnindentedBranchOfConditionalExpression; 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 178 /* SyntaxKind.TypeReference */: return getList(node.typeArguments); case 205 /* SyntaxKind.ObjectLiteralExpression */: return getList(node.properties); case 204 /* SyntaxKind.ArrayLiteralExpression */: return getList(node.elements); case 182 /* SyntaxKind.TypeLiteral */: return getList(node.members); case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: case 174 /* SyntaxKind.CallSignature */: case 171 /* SyntaxKind.Constructor */: case 180 /* SyntaxKind.ConstructorType */: case 175 /* SyntaxKind.ConstructSignature */: return getList(node.typeParameters) || getList(node.parameters); case 172 /* SyntaxKind.GetAccessor */: return getList(node.parameters); case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 344 /* SyntaxKind.JSDocTemplateTag */: return getList(node.typeParameters); case 209 /* SyntaxKind.NewExpression */: case 208 /* SyntaxKind.CallExpression */: return getList(node.typeArguments) || getList(node.arguments); case 255 /* SyntaxKind.VariableDeclarationList */: return getList(node.declarations); case 269 /* SyntaxKind.NamedImports */: case 273 /* SyntaxKind.NamedExports */: return getList(node.elements); case 201 /* SyntaxKind.ObjectBindingPattern */: case 202 /* SyntaxKind.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 /* Value.Unknown */; } return findColumnForFirstNonWhitespaceCharacterInLine(sourceFile.getLineAndCharacterOfPosition(list.pos), sourceFile, options); } function getActualIndentationForListItem(node, sourceFile, options, listIndentsChild) { if (node.parent && node.parent.kind === 255 /* SyntaxKind.VariableDeclarationList */) { // VariableDeclarationList has no wrapping tokens return -1 /* Value.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 /* Value.Unknown */) { return result; } } return getActualIndentationForListStartLine(containingList, sourceFile, options) + (listIndentsChild ? options.indentSize : 0); // TODO: GH#18217 } return -1 /* Value.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 /* SyntaxKind.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 /* Value.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 /* CharacterCodes.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 /* SyntaxKind.Unknown */; switch (parent.kind) { case 238 /* SyntaxKind.ExpressionStatement */: case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 204 /* SyntaxKind.ArrayLiteralExpression */: case 235 /* SyntaxKind.Block */: case 262 /* SyntaxKind.ModuleBlock */: case 205 /* SyntaxKind.ObjectLiteralExpression */: case 182 /* SyntaxKind.TypeLiteral */: case 195 /* SyntaxKind.MappedType */: case 184 /* SyntaxKind.TupleType */: case 263 /* SyntaxKind.CaseBlock */: case 290 /* SyntaxKind.DefaultClause */: case 289 /* SyntaxKind.CaseClause */: case 212 /* SyntaxKind.ParenthesizedExpression */: case 206 /* SyntaxKind.PropertyAccessExpression */: case 208 /* SyntaxKind.CallExpression */: case 209 /* SyntaxKind.NewExpression */: case 237 /* SyntaxKind.VariableStatement */: case 271 /* SyntaxKind.ExportAssignment */: case 247 /* SyntaxKind.ReturnStatement */: case 222 /* SyntaxKind.ConditionalExpression */: case 202 /* SyntaxKind.ArrayBindingPattern */: case 201 /* SyntaxKind.ObjectBindingPattern */: case 280 /* SyntaxKind.JsxOpeningElement */: case 283 /* SyntaxKind.JsxOpeningFragment */: case 279 /* SyntaxKind.JsxSelfClosingElement */: case 288 /* SyntaxKind.JsxExpression */: case 168 /* SyntaxKind.MethodSignature */: case 174 /* SyntaxKind.CallSignature */: case 175 /* SyntaxKind.ConstructSignature */: case 164 /* SyntaxKind.Parameter */: case 179 /* SyntaxKind.FunctionType */: case 180 /* SyntaxKind.ConstructorType */: case 191 /* SyntaxKind.ParenthesizedType */: case 210 /* SyntaxKind.TaggedTemplateExpression */: case 218 /* SyntaxKind.AwaitExpression */: case 273 /* SyntaxKind.NamedExports */: case 269 /* SyntaxKind.NamedImports */: case 275 /* SyntaxKind.ExportSpecifier */: case 270 /* SyntaxKind.ImportSpecifier */: case 167 /* SyntaxKind.PropertyDeclaration */: return true; case 254 /* SyntaxKind.VariableDeclaration */: case 296 /* SyntaxKind.PropertyAssignment */: case 221 /* SyntaxKind.BinaryExpression */: if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === 205 /* SyntaxKind.ObjectLiteralExpression */) { // TODO: GH#18217 return rangeIsOnOneLine(sourceFile, child); } if (parent.kind === 221 /* SyntaxKind.BinaryExpression */ && sourceFile && child && childKind === 278 /* SyntaxKind.JsxElement */) { var parentStartLine = sourceFile.getLineAndCharacterOfPosition(ts.skipTrivia(sourceFile.text, parent.pos)).line; var childStartLine = sourceFile.getLineAndCharacterOfPosition(ts.skipTrivia(sourceFile.text, child.pos)).line; return parentStartLine !== childStartLine; } if (parent.kind !== 221 /* SyntaxKind.BinaryExpression */) { return true; } break; case 240 /* SyntaxKind.DoStatement */: case 241 /* SyntaxKind.WhileStatement */: case 243 /* SyntaxKind.ForInStatement */: case 244 /* SyntaxKind.ForOfStatement */: case 242 /* SyntaxKind.ForStatement */: case 239 /* SyntaxKind.IfStatement */: case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 169 /* SyntaxKind.MethodDeclaration */: case 171 /* SyntaxKind.Constructor */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: return childKind !== 235 /* SyntaxKind.Block */; case 214 /* SyntaxKind.ArrowFunction */: if (sourceFile && childKind === 212 /* SyntaxKind.ParenthesizedExpression */) { return rangeIsOnOneLine(sourceFile, child); } return childKind !== 235 /* SyntaxKind.Block */; case 272 /* SyntaxKind.ExportDeclaration */: return childKind !== 273 /* SyntaxKind.NamedExports */; case 266 /* SyntaxKind.ImportDeclaration */: return childKind !== 267 /* SyntaxKind.ImportClause */ || (!!child.namedBindings && child.namedBindings.kind !== 269 /* SyntaxKind.NamedImports */); case 278 /* SyntaxKind.JsxElement */: return childKind !== 281 /* SyntaxKind.JsxClosingElement */; case 282 /* SyntaxKind.JsxFragment */: return childKind !== 284 /* SyntaxKind.JsxClosingFragment */; case 188 /* SyntaxKind.IntersectionType */: case 187 /* SyntaxKind.UnionType */: if (childKind === 182 /* SyntaxKind.TypeLiteral */ || childKind === 184 /* SyntaxKind.TupleType */) { return false; } break; } // 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 247 /* SyntaxKind.ReturnStatement */: case 251 /* SyntaxKind.ThrowStatement */: case 245 /* SyntaxKind.ContinueStatement */: case 246 /* SyntaxKind.BreakStatement */: return parent.kind !== 235 /* SyntaxKind.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"; /** Doesn't include whitespace, but does strip comments */ TrailingTriviaOption[TrailingTriviaOption["ExcludeWhitespace"] = 1] = "ExcludeWhitespace"; /** Include trailing trivia */ TrailingTriviaOption[TrailingTriviaOption["Include"] = 2] = "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 /* CharacterCodes.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, hasTrailingComment) { var _a, _b; if (hasTrailingComment === void 0) { hasTrailingComment = false; } var leadingTriviaOption = options.leadingTriviaOption; if (leadingTriviaOption === LeadingTriviaOption.Exclude) { return node.getStart(sourceFile); } if (leadingTriviaOption === LeadingTriviaOption.StartLine) { var startPos = node.getStart(sourceFile); var pos = ts.getLineStartPositionForPosition(startPos, sourceFile); return ts.rangeContainsPosition(node, pos) ? pos : startPos; } 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; } // if node has a trailing comments, use comment end position as the text has already been included. if (hasTrailingComment) { // Check first for leading comments as if the node is the first import, we want to exclude the trivia; // otherwise we get the trailing comments. var comment = ((_a = ts.getLeadingCommentRanges(sourceFile.text, fullStart)) === null || _a === void 0 ? void 0 : _a[0]) || ((_b = ts.getTrailingCommentRanges(sourceFile.text, fullStart)) === null || _b === void 0 ? void 0 : _b[0]); if (comment) { return ts.skipTrivia(sourceFile.text, comment.end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); } } // 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); } /** Return the end position of a multiline comment of it is on another line; otherwise returns `undefined`; */ function getEndPositionOfMultilineTrailingComment(sourceFile, node, options) { var end = node.end; var trailingTriviaOption = options.trailingTriviaOption; if (trailingTriviaOption === TrailingTriviaOption.Include) { // If the trailing comment is a multiline comment that extends to the next lines, // return the end of the comment and track it for the next nodes to adjust. var comments = ts.getTrailingCommentRanges(sourceFile.text, end); if (comments) { var nodeEndLine = ts.getLineOfLocalPosition(sourceFile, node.end); for (var _i = 0, comments_2 = comments; _i < comments_2.length; _i++) { var comment = comments_2[_i]; // Single line can break the loop as trivia will only be this line. // Comments on subsequest lines are also ignored. if (comment.kind === 2 /* SyntaxKind.SingleLineCommentTrivia */ || ts.getLineOfLocalPosition(sourceFile, comment.pos) > nodeEndLine) { break; } // Get the end line of the comment and compare against the end line of the node. // If the comment end line position and the multiline comment extends to multiple lines, // then is safe to return the end position. var commentEndLine = ts.getLineOfLocalPosition(sourceFile, comment.end); if (commentEndLine > nodeEndLine) { return ts.skipTrivia(sourceFile.text, comment.end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); } } } } return undefined; } function getAdjustedEndPosition(sourceFile, node, options) { var _a; var end = node.end; var trailingTriviaOption = options.trailingTriviaOption; if (trailingTriviaOption === TrailingTriviaOption.Exclude) { return end; } if (trailingTriviaOption === TrailingTriviaOption.ExcludeWhitespace) { var comments = ts.concatenate(ts.getTrailingCommentRanges(sourceFile.text, end), ts.getLeadingCommentRanges(sourceFile.text, end)); var realEnd = (_a = comments === null || comments === void 0 ? void 0 : comments[comments.length - 1]) === null || _a === void 0 ? void 0 : _a.end; if (realEnd) { return realEnd; } return end; } var multilineEndPosition = getEndPositionOfMultilineTrailingComment(sourceFile, node, options); if (multilineEndPosition) { return multilineEndPosition; } 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 /* SyntaxKind.CommaToken */ || (candidate.kind === 26 /* SyntaxKind.SemicolonToken */ && node.parent.kind === 205 /* SyntaxKind.ObjectLiteralExpression */)); } 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 = new ts.Map(); // 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 }); }; /** Stop! Consider using `delete` instead, which has logic for deleting nodes from delimited lists. */ 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.deleteNodes = function (sourceFile, nodes, options, hasTrailingComment) { if (options === void 0) { options = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }; } // When deleting multiple nodes we need to track if the end position is including multiline trailing comments. for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { var node = nodes_1[_i]; var pos = getAdjustedStartPosition(sourceFile, node, options, hasTrailingComment); var end = getAdjustedEndPosition(sourceFile, node, options); this.deleteRange(sourceFile, { pos: pos, end: end }); hasTrailingComment = !!getEndPositionOfMultilineTrailingComment(sourceFile, 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.nodeHasTrailingComment = function (sourceFile, oldNode, configurableEnd) { if (configurableEnd === void 0) { configurableEnd = useNonAdjustedPositions; } return !!getEndPositionOfMultilineTrailingComment(sourceFile, oldNode, configurableEnd); }; ChangeTracker.prototype.nextCommaToken = function (sourceFile, node) { var next = ts.findNextToken(node, node.parent, sourceFile); return next && next.kind === 27 /* SyntaxKind.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, options) { if (blankLineBetween === void 0) { blankLineBetween = false; } if (options === void 0) { options = {}; } this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); }; ChangeTracker.prototype.insertModifierAt = function (sourceFile, pos, modifier, options) { if (options === void 0) { options = {}; } this.insertNodeAt(sourceFile, pos, ts.factory.createToken(modifier), options); }; ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) { return this.insertModifierAt(sourceFile, before.getStart(sourceFile), modifier, { suffix: " " }); }; 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 = "".concat(insertAtLineStart ? "" : this.newLineCharacter, "//").concat(commentText).concat(this.newLineCharacter).concat(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, { suffix: this.newLineCharacter + indent }); }; ChangeTracker.prototype.createJSDocText = function (sourceFile, node) { var comments = ts.flatMap(node.jsDoc, function (jsDoc) { return ts.isString(jsDoc.comment) ? ts.factory.createJSDocText(jsDoc.comment) : jsDoc.comment; }); var jsDoc = ts.singleOrUndefined(node.jsDoc); return jsDoc && ts.positionsAreOnSameLine(jsDoc.pos, jsDoc.end, sourceFile) && ts.length(comments) === 0 ? undefined : ts.factory.createNodeArray(ts.intersperse(comments, ts.factory.createJSDocText("\n"))); }; ChangeTracker.prototype.replaceJSDocComment = function (sourceFile, node, tags) { this.insertJsdocCommentBefore(sourceFile, updateJSDocHost(node), ts.factory.createJSDocComment(this.createJSDocText(sourceFile, node), ts.factory.createNodeArray(tags))); }; ChangeTracker.prototype.addJSDocTags = function (sourceFile, parent, newTags) { var oldTags = ts.flatMapToMutable(parent.jsDoc, function (j) { return j.tags; }); var unmergedNewTags = newTags.filter(function (newTag) { return !oldTags.some(function (tag, i) { var merged = tryMergeJsdocTags(tag, newTag); if (merged) oldTags[i] = merged; return !!merged; }); }); this.replaceJSDocComment(sourceFile, parent, __spreadArray(__spreadArray([], oldTags, true), unmergedNewTags, true)); }; ChangeTracker.prototype.filterJSDocTags = function (sourceFile, parent, predicate) { this.replaceJSDocComment(sourceFile, parent, ts.filter(ts.flatMapToMutable(parent.jsDoc, function (j) { return j.tags; }), predicate)); }; 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 /* SyntaxKind.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 === 254 /* SyntaxKind.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 /* SyntaxKind.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 /* SyntaxKind.OpenParenToken */, sourceFile) || ts.first(node.parameters)).getStart(sourceFile); this.insertNodesAt(sourceFile, start, typeParameters, { prefix: "<", suffix: ">", joiner: ", " }); }; ChangeTracker.prototype.getOptionsForInsertNodeBefore = function (before, inserted, blankLineBetween) { if (ts.isStatement(before) || ts.isClassElement(before)) { return { suffix: blankLineBetween ? 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: ", " }; } else if (ts.isImportSpecifier(before)) { return { suffix: "," + (blankLineBetween ? this.newLineCharacter : " ") }; } 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, __spreadArray([newStatement], ctr.body.statements, true)); } else { this.insertNodeBefore(sourceFile, firstStatement, newStatement); } }; ChangeTracker.prototype.insertNodeAtConstructorStartAfterSuperCall = function (sourceFile, ctr, newStatement) { var superCallStatement = ts.find(ctr.body.statements, function (stmt) { return ts.isExpressionStatement(stmt) && ts.isSuperCall(stmt.expression); }); if (!superCallStatement || !ctr.body.multiLine) { this.replaceConstructorBody(sourceFile, ctr, __spreadArray(__spreadArray([], ctr.body.statements, true), [newStatement], false)); } else { this.insertNodeAfter(sourceFile, superCallStatement, newStatement); } }; ChangeTracker.prototype.insertNodeAtConstructorEnd = function (sourceFile, ctr, newStatement) { var lastStatement = ts.lastOrUndefined(ctr.body.statements); if (!lastStatement || !ctr.body.multiLine) { this.replaceConstructorBody(sourceFile, ctr, __spreadArray(__spreadArray([], ctr.body.statements, true), [newStatement], false)); } else { this.insertNodeAfter(sourceFile, lastStatement, newStatement); } }; ChangeTracker.prototype.replaceConstructorBody = function (sourceFile, ctr, statements) { this.replaceNode(sourceFile, ctr.body, ts.factory.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.insertMemberAtStart = function (sourceFile, node, newElement) { this.insertNodeAtStartWorker(sourceFile, node, newElement); }; ChangeTracker.prototype.insertNodeAtObjectStart = function (sourceFile, obj, newElement) { this.insertNodeAtStartWorker(sourceFile, obj, newElement); }; ChangeTracker.prototype.insertNodeAtStartWorker = function (sourceFile, node, newElement) { var _a; var indentation = (_a = this.guessIndentationFromExistingMembers(sourceFile, node)) !== null && _a !== void 0 ? _a : this.computeIndentationForNewMember(sourceFile, node); this.insertNodeAt(sourceFile, getMembersOrProperties(node).pos, newElement, this.getInsertNodeAtStartInsertOptions(sourceFile, node, 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, node) { var indentation; var lastRange = node; for (var _i = 0, _a = getMembersOrProperties(node); _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, node) { var _a; var nodeStart = node.getStart(sourceFile); return ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(ts.getLineStartPositionForPosition(nodeStart, sourceFile), nodeStart, sourceFile, this.formatContext.options) + ((_a = this.formatContext.options.indentSize) !== null && _a !== void 0 ? _a : 4); }; ChangeTracker.prototype.getInsertNodeAtStartInsertOptions = function (sourceFile, node, 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(node); var isEmpty = members.length === 0; var isFirstInsertion = ts.addToSeen(this.classesWithNodesInsertedAtStart, ts.getNodeId(node), { node: node, sourceFile: sourceFile }); var insertTrailingComma = ts.isObjectLiteralExpression(node) && (!ts.isJsonSourceFile(sourceFile) || !isEmpty); var insertLeadingComma = ts.isObjectLiteralExpression(node) && 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 /* CharacterCodes.semicolon */) { this.replaceRange(sourceFile, ts.createRange(after.end), ts.factory.createToken(26 /* SyntaxKind.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".concat(options.prefix) : "\n") : options.prefix }); }; ChangeTracker.prototype.getInsertNodeAfterOptionsWorker = function (node) { switch (node.kind) { case 257 /* SyntaxKind.ClassDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: return { prefix: this.newLineCharacter, suffix: this.newLineCharacter }; case 254 /* SyntaxKind.VariableDeclaration */: case 10 /* SyntaxKind.StringLiteral */: case 79 /* SyntaxKind.Identifier */: return { prefix: ", " }; case 296 /* SyntaxKind.PropertyAssignment */: return { suffix: "," + this.newLineCharacter }; case 93 /* SyntaxKind.ExportKeyword */: return { prefix: " " }; case 164 /* SyntaxKind.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 === 214 /* SyntaxKind.ArrowFunction */) { var arrow = ts.findChildOfKind(node, 38 /* SyntaxKind.EqualsGreaterThanToken */, sourceFile); var lparen = ts.findChildOfKind(node, 20 /* SyntaxKind.OpenParenToken */, sourceFile); if (lparen) { // `() => {}` --> `function f() {}` this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [ts.factory.createToken(98 /* SyntaxKind.FunctionKeyword */), ts.factory.createIdentifier(name)], { joiner: " " }); deleteNode(this, sourceFile, arrow); } else { // `x => {}` -> `function f(x) {}` this.insertText(sourceFile, ts.first(node.parameters).getStart(sourceFile), "function ".concat(name, "(")); // Replacing full range of arrow to get rid of the leading space -- replace ` =>` with `)` this.replaceRange(sourceFile, arrow, ts.factory.createToken(21 /* SyntaxKind.CloseParenToken */)); } if (node.body.kind !== 235 /* SyntaxKind.Block */) { // `() => 0` => `function f() { return 0; }` this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [ts.factory.createToken(18 /* SyntaxKind.OpenBraceToken */), ts.factory.createToken(105 /* SyntaxKind.ReturnKeyword */)], { joiner: " ", suffix: " " }); this.insertNodesAt(sourceFile, node.body.end, [ts.factory.createToken(26 /* SyntaxKind.SemicolonToken */), ts.factory.createToken(19 /* SyntaxKind.CloseBraceToken */)], { joiner: " " }); } } else { var pos = ts.findChildOfKind(node, node.kind === 213 /* SyntaxKind.FunctionExpression */ ? 98 /* SyntaxKind.FunctionKeyword */ : 84 /* SyntaxKind.ClassKeyword */, sourceFile).end; this.insertNodeAt(sourceFile, pos, ts.factory.createIdentifier(name), { prefix: " " }); } }; ChangeTracker.prototype.insertExportModifier = function (sourceFile, node) { this.insertText(sourceFile, node.getStart(sourceFile), "export "); }; ChangeTracker.prototype.insertImportSpecifierAtIndex = function (sourceFile, importSpecifier, namedImports, index) { var prevSpecifier = namedImports.elements[index - 1]; if (prevSpecifier) { this.insertNodeInListAfter(sourceFile, prevSpecifier, importSpecifier); } else { this.insertNodeBefore(sourceFile, namedImports.elements[0], importSpecifier, !ts.positionsAreOnSameLine(namedImports.elements[0].getStart(), namedImports.parent.parent.getStart(), sourceFile)); } }; /** * 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 next element start as start and end position in final change // - build text of change by formatting the text of node + 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, var nextNode = containingList[index + 1]; var startPos = skipWhitespacesAndLineBreaks(sourceFile.text, nextNode.getFullStart()); // write separator and leading trivia of the next element as suffix var suffix = "".concat(ts.tokenToString(nextToken.kind)).concat(sourceFile.text.substring(nextToken.end, startPos)); this.insertNodesAt(sourceFile, startPos, [newNode], { 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 /* SyntaxKind.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 /* SyntaxKind.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.factory.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); // find position before "\n" or "\r\n" while (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: "".concat(ts.tokenToString(separator), " ") }); } } }; ChangeTracker.prototype.parenthesizeExpression = function (sourceFile, expression) { this.replaceRange(sourceFile, ts.rangeOfNode(expression), ts.factory.createParenthesizedExpression(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.Set(); // Stores nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`. var _loop_11 = 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(sourceFile, 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_11(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; function updateJSDocHost(parent) { if (parent.kind !== 214 /* SyntaxKind.ArrowFunction */) { return parent; } var jsDocNode = parent.parent.kind === 167 /* SyntaxKind.PropertyDeclaration */ ? parent.parent : parent.parent.parent; jsDocNode.jsDoc = parent.jsDoc; jsDocNode.jsDocCache = parent.jsDocCache; return jsDocNode; } function tryMergeJsdocTags(oldTag, newTag) { if (oldTag.kind !== newTag.kind) { return undefined; } switch (oldTag.kind) { case 340 /* SyntaxKind.JSDocParameterTag */: { var oldParam = oldTag; var newParam = newTag; return ts.isIdentifier(oldParam.name) && ts.isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText ? ts.factory.createJSDocParameterTag(/*tagName*/ undefined, newParam.name, /*isBracketed*/ false, newParam.typeExpression, newParam.isNameFirst, oldParam.comment) : undefined; } case 341 /* SyntaxKind.JSDocReturnTag */: return ts.factory.createJSDocReturnTag(/*tagName*/ undefined, newTag.typeExpression, oldTag.comment); case 343 /* SyntaxKind.JSDocTypeTag */: return ts.factory.createJSDocTypeTag(/*tagName*/ undefined, newTag.typeExpression, oldTag.comment); } } // 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 /* SyntaxKind.OpenBraceToken */, sourceFile); var close = ts.findChildOfKind(cls, 19 /* SyntaxKind.CloseBraceToken */, sourceFile); return [open === null || open === void 0 ? void 0 : open.end, close === null || close === void 0 ? void 0 : close.end]; } function getMembersOrProperties(node) { return ts.isObjectLiteralExpression(node) ? node.properties : node.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_12 = function (i) { ts.Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", function () { return "".concat(JSON.stringify(normalized[i].range), " and ").concat(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_12(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 s === 4 /* SyntaxKind.NewLineTrivia */ ? "" : getNonformattedText(s, oldFile, newLineCharacter).text; }).join(newLineCharacter); var sourceFile = ts.createSourceFile("any file name", nonFormattedText, 99 /* ScriptTarget.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) { var _a; if (change.kind === ChangeKind.Remove) { return ""; } if (change.kind === ChangeKind.Text) { return change.text; } var _b = change.options, options = _b === void 0 ? {} : _b, 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(((_a = change.options) === null || _a === void 0 ? void 0 : _a.joiner) || newLineCharacter) : format(change.node); // strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line var noIndent = (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); } /** 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 = ts.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 = ts.getNewLineKind(newLineCharacter); ts.createPrinter({ newLine: newLine, neverAsciiEscape: true, preserveSourceNewlines: true, terminateUnterminatedLiterals: true }, writer).writeNode(4 /* EmitHint.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 = "".concat(text.substring(0, span.start)).concat(newText).concat(text.substring(ts.textSpanEnd(span))); } return text; } textChanges_3.applyChanges = applyChanges; function isTrivia(s) { return ts.skipTrivia(s, 0) === s.length; } // A transformation context that won't perform parenthesization, as some parenthesization rules // are more aggressive than is strictly necessary. var textChangesTransformationContext = __assign(__assign({}, ts.nullTransformationContext), { factory: ts.createNodeFactory(ts.nullTransformationContext.factory.flags | 1 /* NodeFactoryFlags.NoParenthesizerRules */, ts.nullTransformationContext.factory.baseFactory) }); function assignPositionsToNode(node) { var visited = ts.visitEachChild(node, assignPositionsToNode, textChangesTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); // create proxy node for non synthesized nodes var newNode = ts.nodeIsSynthesized(visited) ? visited : Object.create(visited); ts.setTextRangePosEnd(newNode, getPos(node), getEnd(node)); return newNode; } textChanges_3.assignPositionsToNode = assignPositionsToNode; 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.factory.createNodeArray(visited.slice(0)) : visited; ts.setTextRangePosEnd(nodeArray, getPos(nodes), getEnd(nodes)); return nodeArray; } function createWriter(newLine) { var lastNonTriviaPosition = 0; var writer = ts.createTextWriter(newLine); var onBeforeEmitNode = function (node) { if (node) { setPos(node, lastNonTriviaPosition); } }; var onAfterEmitNode = function (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 { onBeforeEmitNode: onBeforeEmitNode, onAfterEmitNode: onAfterEmitNode, 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 }; } textChanges_3.createWriter = createWriter; 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 /* SyntaxKind.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 /* CharacterCodes.carriageReturn */ && text.charCodeAt(position) === 10 /* CharacterCodes.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 === 162 /* SyntaxKind.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 164 /* SyntaxKind.Parameter */: { var oldFunction = node.parent; if (ts.isArrowFunction(oldFunction) && oldFunction.parameters.length === 1 && !ts.findChildOfKind(oldFunction, 20 /* SyntaxKind.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 266 /* SyntaxKind.ImportDeclaration */: case 265 /* SyntaxKind.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 203 /* SyntaxKind.BindingElement */: var pattern = node.parent; var preserveComma = pattern.kind === 202 /* SyntaxKind.ArrayBindingPattern */ && node !== ts.last(pattern.elements); if (preserveComma) { deleteNode(changes, sourceFile, node); } else { deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); } break; case 254 /* SyntaxKind.VariableDeclaration */: deleteVariableDeclaration(changes, deletedNodesInLists, sourceFile, node); break; case 163 /* SyntaxKind.TypeParameter */: deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); break; case 270 /* SyntaxKind.ImportSpecifier */: var namedImports = node.parent; if (namedImports.elements.length === 1) { deleteImportBinding(changes, sourceFile, namedImports); } else { deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); } break; case 268 /* SyntaxKind.NamespaceImport */: deleteImportBinding(changes, sourceFile, node); break; case 26 /* SyntaxKind.SemicolonToken */: deleteNode(changes, sourceFile, node, { trailingTriviaOption: TrailingTriviaOption.Exclude }); break; case 98 /* SyntaxKind.FunctionKeyword */: deleteNode(changes, sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.Exclude }); break; case 257 /* SyntaxKind.ClassDeclaration */: case 256 /* SyntaxKind.FunctionDeclaration */: deleteNode(changes, sourceFile, node, { leadingTriviaOption: ts.hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine }); break; default: if (!node.parent) { // a misbehaving client can reach here with the SourceFile node deleteNode(changes, sourceFile, node); } else 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 /* SyntaxKind.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, 266 /* SyntaxKind.ImportDeclaration */); deleteNode(changes, sourceFile, importDecl); } } function deleteVariableDeclaration(changes, deletedNodesInLists, sourceFile, node) { var parent = node.parent; if (parent.kind === 292 /* SyntaxKind.CatchClause */) { // TODO: There's currently no unused diagnostic for this, could be a suggestion changes.deleteNodeRange(sourceFile, ts.findChildOfKind(parent, 20 /* SyntaxKind.OpenParenToken */, sourceFile), ts.findChildOfKind(parent, 21 /* SyntaxKind.CloseParenToken */, sourceFile)); return; } if (parent.declarations.length !== 1) { deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); return; } var gp = parent.parent; switch (gp.kind) { case 244 /* SyntaxKind.ForOfStatement */: case 243 /* SyntaxKind.ForInStatement */: changes.replaceNode(sourceFile, node, ts.factory.createObjectLiteralExpression()); break; case 242 /* SyntaxKind.ForStatement */: deleteNode(changes, sourceFile, parent); break; case 237 /* SyntaxKind.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 = new ts.Map(); function createCodeFixActionWithoutFixAll(fixName, changes, description) { return createCodeFixActionWorker(fixName, ts.diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined); } codefix.createCodeFixActionWithoutFixAll = createCodeFixActionWithoutFixAll; function createCodeFixAction(fixName, changes, description, fixId, fixAllDescription, command) { return createCodeFixActionWorker(fixName, ts.diagnosticToString(description), changes, fixId, ts.diagnosticToString(fixAllDescription), command); } codefix.createCodeFixAction = createCodeFixAction; function createCodeFixActionMaybeFixAll(fixName, changes, description, fixId, fixAllDescription, command) { return createCodeFixActionWorker(fixName, ts.diagnosticToString(description), changes, fixId, fixAllDescription && ts.diagnosticToString(fixAllDescription), command); } codefix.createCodeFixActionMaybeFixAll = createCodeFixActionMaybeFixAll; 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 __spreadArray(__spreadArray(__spreadArray([], program.getSemanticDiagnostics(sourceFile, cancellationToken), true), program.getSyntacticDiagnostics(sourceFile, cancellationToken), true), ts.computeSuggestionDiagnostics(sourceFile, program, cancellationToken), true); } })(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 = new ts.Map(); /** @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) { var _a; return context.cancellationToken && context.cancellationToken.isCancellationRequested() || !((_a = refactor.kinds) === null || _a === void 0 ? void 0 : _a.some(function (kind) { return refactor_1.refactorKindBeginsWith(kind, context.kind); })) ? 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 getCodeActionsToAddConvertToUnknownForNonOverlappingTypes(context) { var assertion = getAssertion(context.sourceFile, context.span.start); if (assertion === undefined) return undefined; var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, assertion); }); 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) { var assertion = getAssertion(diag.file, diag.start); if (assertion) { makeChange(changes, diag.file, assertion); } }); }, }); function makeChange(changeTracker, sourceFile, assertion) { var replacement = ts.isAsExpression(assertion) ? ts.factory.createAsExpression(assertion.expression, ts.factory.createKeywordTypeNode(155 /* SyntaxKind.UnknownKeyword */)) : ts.factory.createTypeAssertion(ts.factory.createKeywordTypeNode(155 /* SyntaxKind.UnknownKeyword */), assertion.expression); changeTracker.replaceNode(sourceFile, assertion.expression, replacement); } function getAssertion(sourceFile, pos) { if (ts.isInJSFile(sourceFile)) return undefined; return ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos), function (n) { return ts.isAsExpression(n) || ts.isTypeAssertionExpression(n); }); } })(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, ts.Diagnostics.for_await_loops_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 getCodeActionsToAddEmptyExportDeclaration(context) { var sourceFile = context.sourceFile; var changes = ts.textChanges.ChangeTracker.with(context, function (changes) { var exportDeclaration = ts.factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, ts.factory.createNamedExports([]), /*moduleSpecifier*/ undefined); 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 getCodeActionsToAddMissingAsync(context) { var sourceFile = context.sourceFile, errorCode = context.errorCode, cancellationToken = context.cancellationToken, program = context.program, span = context.span; var diagnostic = ts.find(program.getTypeChecker().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 = new ts.Set(); 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))) { return; } } fixedDeclarations === null || fixedDeclarations === void 0 ? void 0 : fixedDeclarations.add(ts.getNodeId(insertionSite)); var cloneWithModifier = ts.factory.updateModifiers(ts.getSynthesizedDeepClone(insertionSite, /*includeTrivia*/ true), ts.factory.createNodeArray(ts.factory.createModifiersFromModifierFlags(ts.getSyntacticModifierFlags(insertionSite) | 256 /* ModifierFlags.Async */))); 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 = __spreadArray([ 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.This_condition_will_always_return_true_since_this_0_is_always_defined.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_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher.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, true); codefix.registerCodeFix({ fixIds: [fixId], errorCodes: errorCodes, getCodeActions: function getCodeActionsToAddMissingAwait(context) { var sourceFile = context.sourceFile, errorCode = context.errorCode, span = context.span, cancellationToken = context.cancellationToken, program = context.program; var expression = getAwaitErrorSpanExpression(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 = new ts.Set(); return codefix.codeFixAll(context, errorCodes, function (t, diagnostic) { var expression = getAwaitErrorSpanExpression(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 getAwaitErrorSpanExpression(sourceFile, errorCode, span, cancellationToken, program) { var expression = ts.getFixableErrorSpanExpression(sourceFile, span); return expression && isMissingAwaitError(sourceFile, errorCode, span, cancellationToken, program) && isInsideAwaitableBody(expression) ? expression : undefined; } 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.getTypeChecker(); 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 findAwaitableInitializers(expression, sourceFile, cancellationToken, program, checker) { var identifiers = getIdentifiersFromErrorSpanExpression(expression, checker); if (!identifiers) { return; } var isCompleteFix = identifiers.isCompleteFix; var initializers; var _loop_13 = 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, 237 /* SyntaxKind.VariableStatement */); if (!declaration || !variableStatement || declaration.type || !declaration.initializer || variableStatement.getSourceFile() !== sourceFile || ts.hasSyntacticModifier(variableStatement, 1 /* ModifierFlags.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_13(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 /* TypeFlags.Any */; } function isInsideAwaitableBody(node) { return node.kind & 32768 /* NodeFlags.AwaitContext */ || !!ts.findAncestor(node, function (ancestor) { return ancestor.parent && ts.isArrowFunction(ancestor.parent) && ancestor.parent.body === ancestor || ts.isBlock(ancestor) && (ancestor.parent.kind === 256 /* SyntaxKind.FunctionDeclaration */ || ancestor.parent.kind === 213 /* SyntaxKind.FunctionExpression */ || ancestor.parent.kind === 214 /* SyntaxKind.ArrowFunction */ || ancestor.parent.kind === 169 /* SyntaxKind.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))) { continue; } } var type = checker.getTypeAtLocation(side); var newNode = checker.getPromisedTypeOfPromise(type) ? ts.factory.createAwaitExpression(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))) { return; } } changeTracker.replaceNode(sourceFile, insertionSite.parent.expression, ts.factory.createParenthesizedExpression(ts.factory.createAwaitExpression(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))) { return; } } changeTracker.replaceNode(sourceFile, insertionSite, ts.factory.createParenthesizedExpression(ts.factory.createAwaitExpression(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.tryAddToSet(fixedDeclarations, ts.getSymbolId(symbol))) { return; } } changeTracker.replaceNode(sourceFile, insertionSite, ts.factory.createAwaitExpression(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 getCodeActionsToAddMissingConst(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.Set(); 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 === 63 /* SyntaxKind.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 || ts.tryAddToSet(fixedNodes, initializer)) { changeTracker.insertModifierBefore(sourceFile, 85 /* SyntaxKind.ConstKeyword */, initializer); } } function isPossiblyPartOfDestructuring(node) { switch (node.kind) { case 79 /* SyntaxKind.Identifier */: case 204 /* SyntaxKind.ArrayLiteralExpression */: case 205 /* SyntaxKind.ObjectLiteralExpression */: case 296 /* SyntaxKind.PropertyAssignment */: case 297 /* SyntaxKind.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 79 /* SyntaxKind.Identifier */: case 221 /* SyntaxKind.BinaryExpression */: case 27 /* SyntaxKind.CommaToken */: return true; default: return false; } } function expressionCouldBeVariableDeclaration(expression, checker) { if (!ts.isBinaryExpression(expression)) { return false; } if (expression.operatorToken.kind === 27 /* SyntaxKind.CommaToken */) { return ts.every([expression.left, expression.right], function (expression) { return expressionCouldBeVariableDeclaration(expression, checker); }); } return expression.operatorToken.kind === 63 /* SyntaxKind.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 getCodeActionsToAddMissingDeclareOnProperty(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.Set(); 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 === 167 /* SyntaxKind.PropertyDeclaration */ && (!fixedNodes || ts.tryAddToSet(fixedNodes, declaration))) { changeTracker.insertModifierBefore(sourceFile, 135 /* SyntaxKind.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 getCodeActionsToAddMissingInvocationForDecorator(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.factory.createCallExpression(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 getCodeActionsToAddNameToNamelessParameter(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); 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 typeNode = ts.factory.createTypeReferenceNode(param.name, /*typeArguments*/ undefined); var replacement = ts.factory.createParameterDeclaration( /*decorators*/ undefined, param.modifiers, param.dotDotDotToken, "arg" + i, param.questionToken, param.dotDotDotToken ? ts.factory.createArrayTypeNode(typeNode) : typeNode, param.initializer); changeTracker.replaceNode(sourceFile, param, replacement); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var addOptionalPropertyUndefined = "addOptionalPropertyUndefined"; var errorCodes = [ ts.Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target.code, ts.Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties.code, ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var typeChecker = context.program.getTypeChecker(); var toAdd = getPropertiesToAdd(context.sourceFile, context.span, typeChecker); if (!toAdd.length) { return undefined; } var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addUndefinedToOptionalProperty(t, toAdd); }); return [codefix.createCodeFixActionWithoutFixAll(addOptionalPropertyUndefined, changes, ts.Diagnostics.Add_undefined_to_optional_property_type)]; }, fixIds: [addOptionalPropertyUndefined], }); function getPropertiesToAdd(file, span, checker) { var _a, _b; var sourceTarget = getSourceTarget(ts.getFixableErrorSpanExpression(file, span), checker); if (!sourceTarget) { return ts.emptyArray; } var sourceNode = sourceTarget.source, targetNode = sourceTarget.target; var target = shouldUseParentTypeOfProperty(sourceNode, targetNode, checker) ? checker.getTypeAtLocation(targetNode.expression) : checker.getTypeAtLocation(targetNode); if ((_b = (_a = target.symbol) === null || _a === void 0 ? void 0 : _a.declarations) === null || _b === void 0 ? void 0 : _b.some(function (d) { return ts.getSourceFileOfNode(d).fileName.match(/\.d\.ts$/); })) { return ts.emptyArray; } return checker.getExactOptionalProperties(target); } function shouldUseParentTypeOfProperty(sourceNode, targetNode, checker) { return ts.isPropertyAccessExpression(targetNode) && !!checker.getExactOptionalProperties(checker.getTypeAtLocation(targetNode.expression)).length && checker.getTypeAtLocation(sourceNode) === checker.getUndefinedType(); } /** * Find the source and target of the incorrect assignment. * The call is recursive for property assignments. */ function getSourceTarget(errorNode, checker) { var _a; if (!errorNode) { return undefined; } else if (ts.isBinaryExpression(errorNode.parent) && errorNode.parent.operatorToken.kind === 63 /* SyntaxKind.EqualsToken */) { return { source: errorNode.parent.right, target: errorNode.parent.left }; } else if (ts.isVariableDeclaration(errorNode.parent) && errorNode.parent.initializer) { return { source: errorNode.parent.initializer, target: errorNode.parent.name }; } else if (ts.isCallExpression(errorNode.parent)) { var n = checker.getSymbolAtLocation(errorNode.parent.expression); if (!(n === null || n === void 0 ? void 0 : n.valueDeclaration) || !ts.isFunctionLikeKind(n.valueDeclaration.kind)) return undefined; if (!ts.isExpression(errorNode)) return undefined; var i = errorNode.parent.arguments.indexOf(errorNode); if (i === -1) return undefined; var name = n.valueDeclaration.parameters[i].name; if (ts.isIdentifier(name)) return { source: errorNode, target: name }; } else if (ts.isPropertyAssignment(errorNode.parent) && ts.isIdentifier(errorNode.parent.name) || ts.isShorthandPropertyAssignment(errorNode.parent)) { var parentTarget = getSourceTarget(errorNode.parent.parent, checker); if (!parentTarget) return undefined; var prop = checker.getPropertyOfType(checker.getTypeAtLocation(parentTarget.target), errorNode.parent.name.text); var declaration = (_a = prop === null || prop === void 0 ? void 0 : prop.declarations) === null || _a === void 0 ? void 0 : _a[0]; if (!declaration) return undefined; return { source: ts.isPropertyAssignment(errorNode.parent) ? errorNode.parent.initializer : errorNode.parent.name, target: declaration }; } return undefined; } function addUndefinedToOptionalProperty(changes, toAdd) { for (var _i = 0, toAdd_1 = toAdd; _i < toAdd_1.length; _i++) { var add = toAdd_1[_i]; var d = add.valueDeclaration; if (d && (ts.isPropertySignature(d) || ts.isPropertyDeclaration(d)) && d.type) { var t = ts.factory.createUnionTypeNode(__spreadArray(__spreadArray([], d.type.kind === 187 /* SyntaxKind.UnionType */ ? d.type.types : [d.type], true), [ ts.factory.createTypeReferenceNode("undefined") ], false)); changes.replaceNode(d.getSourceFile(), d.type, t); } } } })(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 /* SyntaxKind.OpenParenToken */, sourceFile); if (needParens) changes.insertNodeBefore(sourceFile, ts.first(decl.parameters), ts.factory.createToken(20 /* SyntaxKind.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.factory.createToken(21 /* SyntaxKind.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 === 254 /* SyntaxKind.VariableDeclaration */ || node.kind === 166 /* SyntaxKind.PropertySignature */ || node.kind === 167 /* SyntaxKind.PropertyDeclaration */; } function transformJSDocType(node) { switch (node.kind) { case 312 /* SyntaxKind.JSDocAllType */: case 313 /* SyntaxKind.JSDocUnknownType */: return ts.factory.createTypeReferenceNode("any", ts.emptyArray); case 316 /* SyntaxKind.JSDocOptionalType */: return transformJSDocOptionalType(node); case 315 /* SyntaxKind.JSDocNonNullableType */: return transformJSDocType(node.type); case 314 /* SyntaxKind.JSDocNullableType */: return transformJSDocNullableType(node); case 318 /* SyntaxKind.JSDocVariadicType */: return transformJSDocVariadicType(node); case 317 /* SyntaxKind.JSDocFunctionType */: return transformJSDocFunctionType(node); case 178 /* SyntaxKind.TypeReference */: return transformJSDocTypeReference(node); default: var visited = ts.visitEachChild(node, transformJSDocType, ts.nullTransformationContext); ts.setEmitFlags(visited, 1 /* EmitFlags.SingleLine */); return visited; } } function transformJSDocOptionalType(node) { return ts.factory.createUnionTypeNode([ts.visitNode(node.type, transformJSDocType), ts.factory.createTypeReferenceNode("undefined", ts.emptyArray)]); } function transformJSDocNullableType(node) { return ts.factory.createUnionTypeNode([ts.visitNode(node.type, transformJSDocType), ts.factory.createTypeReferenceNode("null", ts.emptyArray)]); } function transformJSDocVariadicType(node) { return ts.factory.createArrayTypeNode(ts.visitNode(node.type, transformJSDocType)); } function transformJSDocFunctionType(node) { var _a; // TODO: This does not properly handle `function(new:C, string)` per https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System#the-javascript-type-language // however we do handle it correctly in `serializeTypeForDeclaration` in checker.ts return ts.factory.createFunctionTypeNode(ts.emptyArray, node.parameters.map(transformJSDocParameter), (_a = node.type) !== null && _a !== void 0 ? _a : ts.factory.createKeywordTypeNode(130 /* SyntaxKind.AnyKeyword */)); } function transformJSDocParameter(node) { var index = node.parent.parameters.indexOf(node); var isRest = node.type.kind === 318 /* SyntaxKind.JSDocVariadicType */ && index === node.parent.parameters.length - 1; // TODO: GH#18217 var name = node.name || (isRest ? "rest" : "arg" + index); var dotdotdot = isRest ? ts.factory.createToken(25 /* SyntaxKind.DotDotDotToken */) : node.dotDotDotToken; return ts.factory.createParameterDeclaration(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.factory.createIdentifier(text); if ((text === "Array" || text === "Promise") && !node.typeArguments) { args = ts.factory.createNodeArray([ts.factory.createTypeReferenceNode("any", ts.emptyArray)]); } else { args = ts.visitNodes(node.typeArguments, transformJSDocType); } } return ts.factory.createTypeReferenceNode(name, args); } function transformJSDocIndexSignature(node) { var index = ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, node.typeArguments[0].kind === 147 /* SyntaxKind.NumberKeyword */ ? "n" : "s", /*questionToken*/ undefined, ts.factory.createTypeReferenceNode(node.typeArguments[0].kind === 147 /* SyntaxKind.NumberKeyword */ ? "number" : "string", []), /*initializer*/ undefined); var indexSignature = ts.factory.createTypeLiteralNode([ts.factory.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments[1])]); ts.setEmitFlags(indexSignature, 1 /* EmitFlags.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(), context.preferences, context.program.getCompilerOptions()); }); 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(), context.preferences, context.program.getCompilerOptions()); }); }, }); function doChange(changes, sourceFile, position, checker, preferences, compilerOptions) { var ctorSymbol = checker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, position)); if (!ctorSymbol || !ctorSymbol.valueDeclaration || !(ctorSymbol.flags & (16 /* SymbolFlags.Function */ | 3 /* SymbolFlags.Variable */))) { // Bad input return undefined; } var ctorDeclaration = ctorSymbol.valueDeclaration; if (ts.isFunctionDeclaration(ctorDeclaration)) { changes.replaceNode(sourceFile, ctorDeclaration, createClassFromFunctionDeclaration(ctorDeclaration)); } else if (ts.isVariableDeclaration(ctorDeclaration)) { var classDeclaration = createClassFromVariableDeclaration(ctorDeclaration); if (!classDeclaration) { return undefined; } var ancestor = ctorDeclaration.parent.parent; if (ts.isVariableDeclarationList(ctorDeclaration.parent) && ctorDeclaration.parent.declarations.length > 1) { changes.delete(sourceFile, ctorDeclaration); changes.insertNodeAfter(sourceFile, ancestor, classDeclaration); } else { changes.replaceNode(sourceFile, ancestor, classDeclaration); } } function createClassElementsFromSymbol(symbol) { var memberElements = []; // all static members are stored in the "exports" array of symbol if (symbol.exports) { symbol.exports.forEach(function (member) { if (member.name === "prototype" && member.declarations) { var firstDeclaration = member.declarations[0]; // only one "x.prototype = { ... }" will pass if (member.declarations.length === 1 && ts.isPropertyAccessExpression(firstDeclaration) && ts.isBinaryExpression(firstDeclaration.parent) && firstDeclaration.parent.operatorToken.kind === 63 /* SyntaxKind.EqualsToken */ && ts.isObjectLiteralExpression(firstDeclaration.parent.right)) { var prototypes = firstDeclaration.parent.right; createClassElement(prototypes.symbol, /** modifiers */ undefined, memberElements); } } else { createClassElement(member, [ts.factory.createToken(124 /* SyntaxKind.StaticKeyword */)], memberElements); } }); } // all instance members are stored in the "member" array of symbol (done last so instance members pulled from prototype assignments have priority) if (symbol.members) { symbol.members.forEach(function (member, key) { var _a, _b, _c, _d; if (key === "constructor" && member.valueDeclaration) { var prototypeAssignment = (_d = (_c = (_b = (_a = symbol.exports) === null || _a === void 0 ? void 0 : _a.get("prototype")) === null || _b === void 0 ? void 0 : _b.declarations) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.parent; if (prototypeAssignment && ts.isBinaryExpression(prototypeAssignment) && ts.isObjectLiteralExpression(prototypeAssignment.right) && ts.some(prototypeAssignment.right.properties, isConstructorAssignment)) { // fn.prototype = { constructor: fn } // Already deleted in `createClassElement` in first pass } else { // fn.prototype.constructor = fn changes.delete(sourceFile, member.valueDeclaration.parent); } return; } createClassElement(member, /*modifiers*/ undefined, memberElements); }); } return memberElements; function shouldConvertDeclaration(_target, source) { // Right now the only thing we can convert are function expressions, get/set accessors and methods // other values like normal value fields ({a: 1}) shouldn't get transformed. // We can update this once ES public class properties are available. if (ts.isAccessExpression(_target)) { if (ts.isPropertyAccessExpression(_target) && isConstructorAssignment(_target)) return true; return ts.isFunctionLike(source); } else { return ts.every(_target.properties, function (property) { // a() {} if (ts.isMethodDeclaration(property) || ts.isGetOrSetAccessorDeclaration(property)) return true; // a: function() {} if (ts.isPropertyAssignment(property) && ts.isFunctionExpression(property.initializer) && !!property.name) return true; // x.prototype.constructor = fn if (isConstructorAssignment(property)) return true; return false; }); } } function createClassElement(symbol, modifiers, members) { // Right now the only thing we can convert are function expressions, which are marked as methods // or { x: y } type prototype assignments, which are marked as ObjectLiteral if (!(symbol.flags & 8192 /* SymbolFlags.Method */) && !(symbol.flags & 4096 /* SymbolFlags.ObjectLiteral */)) { return; } var memberDeclaration = symbol.valueDeclaration; var assignmentBinaryExpression = memberDeclaration.parent; var assignmentExpr = assignmentBinaryExpression.right; if (!shouldConvertDeclaration(memberDeclaration, assignmentExpr)) { return; } if (ts.some(members, function (m) { var name = ts.getNameOfDeclaration(m); if (name && ts.isIdentifier(name) && ts.idText(name) === ts.symbolName(symbol)) { return true; // class member already made for this name } return false; })) { 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 === 238 /* SyntaxKind.ExpressionStatement */ ? assignmentBinaryExpression.parent : assignmentBinaryExpression; changes.delete(sourceFile, nodeToDelete); if (!assignmentExpr) { members.push(ts.factory.createPropertyDeclaration([], modifiers, symbol.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); return; } // f.x = expr if (ts.isAccessExpression(memberDeclaration) && (ts.isFunctionExpression(assignmentExpr) || ts.isArrowFunction(assignmentExpr))) { var quotePreference = ts.getQuotePreference(sourceFile, preferences); var name = tryGetPropertyName(memberDeclaration, compilerOptions, quotePreference); if (name) { createFunctionLikeExpressionMember(members, assignmentExpr, name); } return; } // f.prototype = { ... } else if (ts.isObjectLiteralExpression(assignmentExpr)) { ts.forEach(assignmentExpr.properties, function (property) { if (ts.isMethodDeclaration(property) || ts.isGetOrSetAccessorDeclaration(property)) { // MethodDeclaration and AccessorDeclaration can appear in a class directly members.push(property); } if (ts.isPropertyAssignment(property) && ts.isFunctionExpression(property.initializer)) { createFunctionLikeExpressionMember(members, property.initializer, property.name); } // Drop constructor assignments if (isConstructorAssignment(property)) return; return; }); return; } else { // Don't try to declare members in JavaScript files if (ts.isSourceFileJS(sourceFile)) return; if (!ts.isPropertyAccessExpression(memberDeclaration)) return; var prop = ts.factory.createPropertyDeclaration(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, /*type*/ undefined, assignmentExpr); ts.copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile); members.push(prop); return; } function createFunctionLikeExpressionMember(members, expression, name) { if (ts.isFunctionExpression(expression)) return createFunctionExpressionMember(members, expression, name); else return createArrowFunctionExpressionMember(members, expression, name); } function createFunctionExpressionMember(members, functionExpression, name) { var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 131 /* SyntaxKind.AsyncKeyword */)); var method = ts.factory.createMethodDeclaration(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, name, /*questionToken*/ undefined, /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body); ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); members.push(method); return; } function createArrowFunctionExpressionMember(members, arrowFunction, name) { var arrowFunctionBody = arrowFunction.body; var bodyBlock; // case 1: () => { return [1,2,3] } if (arrowFunctionBody.kind === 235 /* SyntaxKind.Block */) { bodyBlock = arrowFunctionBody; } // case 2: () => [1,2,3] else { bodyBlock = ts.factory.createBlock([ts.factory.createReturnStatement(arrowFunctionBody)]); } var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 131 /* SyntaxKind.AsyncKeyword */)); var method = ts.factory.createMethodDeclaration(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, name, /*questionToken*/ undefined, /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock); ts.copyLeadingComments(assignmentBinaryExpression, method, sourceFile); members.push(method); } } } function createClassFromVariableDeclaration(node) { var initializer = node.initializer; if (!initializer || !ts.isFunctionExpression(initializer) || !ts.isIdentifier(node.name)) { return undefined; } var memberElements = createClassElementsFromSymbol(node.symbol); if (initializer.body) { memberElements.unshift(ts.factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body)); } var modifiers = getModifierKindFromSource(node.parent.parent, 93 /* SyntaxKind.ExportKeyword */); var cls = ts.factory.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.factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body)); } var modifiers = getModifierKindFromSource(node, 93 /* SyntaxKind.ExportKeyword */); var cls = ts.factory.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; }); } function isConstructorAssignment(x) { if (!x.name) return false; if (ts.isIdentifier(x.name) && x.name.text === "constructor") return true; return false; } function tryGetPropertyName(node, compilerOptions, quotePreference) { if (ts.isPropertyAccessExpression(node)) { return node.name; } var propName = node.argumentExpression; if (ts.isNumericLiteral(propName)) { return propName; } if (ts.isStringLiteralLike(propName)) { return ts.isIdentifierText(propName.text, ts.getEmitScriptTarget(compilerOptions)) ? ts.factory.createIdentifier(propName.text) : ts.isNoSubstitutionTemplateLiteral(propName) ? ts.factory.createStringLiteral(propName.text, quotePreference === 0 /* QuotePreference.Single */) : propName; } return undefined; } })(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()); }); 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()); }); }, }); var SynthBindingNameKind; (function (SynthBindingNameKind) { SynthBindingNameKind[SynthBindingNameKind["Identifier"] = 0] = "Identifier"; SynthBindingNameKind[SynthBindingNameKind["BindingPattern"] = 1] = "BindingPattern"; })(SynthBindingNameKind || (SynthBindingNameKind = {})); function convertToAsyncFunction(changes, sourceFile, position, checker) { // 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.canBeConvertedToAsync); } if (!functionToConvert) { return; } var synthNamesMap = new ts.Map(); var isInJavascript = ts.isInJSFile(functionToConvert); var setOfExpressionsToReturn = getAllPromiseExpressionsToReturn(functionToConvert, checker); var functionToConvertRenamed = renameCollidingVarNames(functionToConvert, checker, synthNamesMap); if (!ts.returnsPromise(functionToConvertRenamed, checker)) { return; } var returnStatements = functionToConvertRenamed.body && ts.isBlock(functionToConvertRenamed.body) ? getReturnStatementsWithPromiseHandlers(functionToConvertRenamed.body, checker) : ts.emptyArray; var transformer = { checker: checker, synthNamesMap: synthNamesMap, setOfExpressionsToReturn: setOfExpressionsToReturn, isInJSFile: isInJavascript }; if (!returnStatements.length) { return; } var pos = functionToConvert.modifiers ? functionToConvert.modifiers.end : functionToConvert.decorators ? ts.skipTrivia(sourceFile.text, functionToConvert.decorators.end) : functionToConvert.getStart(sourceFile); var options = functionToConvert.modifiers ? { prefix: " " } : { suffix: " " }; changes.insertModifierAt(sourceFile, pos, 131 /* SyntaxKind.AsyncKeyword */, options); var _loop_14 = function (returnStatement) { ts.forEachChild(returnStatement, function visit(node) { if (ts.isCallExpression(node)) { var newNodes = transformExpression(node, node, transformer, /*hasContinuation*/ false); if (hasFailed()) { return true; // return something truthy to shortcut out of more work } changes.replaceNodeWithNodes(sourceFile, returnStatement, newNodes); } else if (!ts.isFunctionLike(node)) { ts.forEachChild(node, visit); if (hasFailed()) { return true; // return something truthy to shortcut out of more work } } }); if (hasFailed()) { return { value: void 0 }; } }; for (var _i = 0, returnStatements_1 = returnStatements; _i < returnStatements_1.length; _i++) { var returnStatement = returnStatements_1[_i]; var state_5 = _loop_14(returnStatement); if (typeof state_5 === "object") return state_5.value; } } function getReturnStatementsWithPromiseHandlers(body, checker) { var res = []; ts.forEachReturnStatement(body, function (ret) { if (ts.isReturnStatementWithFixablePromiseHandler(ret, checker)) 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 new ts.Set(); } var setOfExpressionsToReturn = new ts.Set(); ts.forEachChild(func.body, function visit(node) { if (isPromiseReturningCallExpression(node, checker, "then")) { setOfExpressionsToReturn.add(ts.getNodeId(node)); ts.forEach(node.arguments, visit); } else if (isPromiseReturningCallExpression(node, checker, "catch") || isPromiseReturningCallExpression(node, checker, "finally")) { setOfExpressionsToReturn.add(ts.getNodeId(node)); // if .catch() or .finally() 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.add(ts.getNodeId(node)); // 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)); } // NOTE: this is a mostly copy of `isReferenceToType` from checker.ts. While this violates DRY, it keeps // `isReferenceToType` in checker local to the checker to avoid the cost of a property lookup on `ts`. function isReferenceToType(type, target) { return (ts.getObjectFlags(type) & 4 /* ObjectFlags.Reference */) !== 0 && type.target === target; } function getExplicitPromisedTypeOfPromiseReturningCallExpression(node, callback, checker) { if (node.expression.name.escapedText === "finally") { // for a `finally`, there's no type argument return undefined; } // If the call to `then` or `catch` comes from the global `Promise` or `PromiseLike` type, we can safely use the // type argument supplied for the callback. For other promise types we would need a more complex heuristic to determine // which type argument is safe to use as an annotation. var promiseType = checker.getTypeAtLocation(node.expression.expression); if (isReferenceToType(promiseType, checker.getPromiseType()) || isReferenceToType(promiseType, checker.getPromiseLikeType())) { if (node.expression.name.escapedText === "then") { if (callback === ts.elementAt(node.arguments, 0)) { // for the `onfulfilled` callback, use the first type argument return ts.elementAt(node.typeArguments, 0); } else if (callback === ts.elementAt(node.arguments, 1)) { // for the `onrejected` callback, use the second type argument return ts.elementAt(node.typeArguments, 1); } } else { return ts.elementAt(node.typeArguments, 0); } } } function isPromiseTypedExpression(node, checker) { if (!ts.isExpression(node)) return false; return !!checker.getPromisedTypeOfPromise(checker.getTypeAtLocation(node)); } /* Renaming of identifiers may be necessary 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) { var identsToRenameMap = new ts.Map(); // 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); if (symbol) { 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.isParameter(node.parent) && !ts.isFunctionLikeDeclaration(node.parent) && !synthNamesMap.has(symbolIdString)) { var firstParameter = ts.firstOrUndefined(lastCallSignature.parameters); var ident = (firstParameter === null || firstParameter === void 0 ? void 0 : firstParameter.valueDeclaration) && ts.isParameter(firstParameter.valueDeclaration) && ts.tryCast(firstParameter.valueDeclaration.name, ts.isIdentifier) || ts.factory.createUniqueName("result", 16 /* GeneratedIdentifierFlags.Optimistic */); 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.getSynthesizedDeepCloneWithReplacements(nodeToRename, /*includeTrivia*/ true, function (original) { if (ts.isBindingElement(original) && ts.isIdentifier(original.name) && ts.isObjectBindingPattern(original.parent)) { var symbol = checker.getSymbolAtLocation(original.name); var renameInfo = symbol && identsToRenameMap.get(String(ts.getSymbolId(symbol))); if (renameInfo && renameInfo.text !== (original.name || original.propertyName).getText()) { return ts.factory.createBindingElement(original.dotDotDotToken, original.propertyName || original.name, renameInfo, original.initializer); } } else if (ts.isIdentifier(original)) { var symbol = checker.getSymbolAtLocation(original); var renameInfo = symbol && identsToRenameMap.get(String(ts.getSymbolId(symbol))); if (renameInfo) { return ts.factory.createIdentifier(renameInfo.text); } } }); } function getNewNameIfConflict(name, originalNames) { var numVarsSameName = (originalNames.get(name.text) || ts.emptyArray).length; var identifier = numVarsSameName === 0 ? name : ts.factory.createIdentifier(name.text + "_" + numVarsSameName); return createSynthIdentifier(identifier); } function hasFailed() { return !codeActionSucceeded; } 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 /** * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows the continuation to which this expression belongs. * @param continuationArgName The argument name for the continuation that follows this call. */ function transformExpression(returnContextNode, node, transformer, hasContinuation, continuationArgName) { if (isPromiseReturningCallExpression(node, transformer.checker, "then")) { return transformThen(node, ts.elementAt(node.arguments, 0), ts.elementAt(node.arguments, 1), transformer, hasContinuation, continuationArgName); } if (isPromiseReturningCallExpression(node, transformer.checker, "catch")) { return transformCatch(node, ts.elementAt(node.arguments, 0), transformer, hasContinuation, continuationArgName); } if (isPromiseReturningCallExpression(node, transformer.checker, "finally")) { return transformFinally(node, ts.elementAt(node.arguments, 0), transformer, hasContinuation, continuationArgName); } if (ts.isPropertyAccessExpression(node)) { return transformExpression(returnContextNode, node.expression, transformer, hasContinuation, continuationArgName); } var nodeType = transformer.checker.getTypeAtLocation(node); if (nodeType && transformer.checker.getPromisedTypeOfPromise(nodeType)) { ts.Debug.assertNode(ts.getOriginalNode(node).parent, ts.isPropertyAccessExpression); return transformPromiseExpressionOfPropertyAccess(returnContextNode, node, transformer, hasContinuation, continuationArgName); } return silentFail(); } function isNullOrUndefined(_a, node) { var checker = _a.checker; if (node.kind === 104 /* SyntaxKind.NullKeyword */) return true; if (ts.isIdentifier(node) && !ts.isGeneratedIdentifier(node) && ts.idText(node) === "undefined") { var symbol = checker.getSymbolAtLocation(node); return !symbol || checker.isUndefinedSymbol(symbol); } return false; } function createUniqueSynthName(prevArgName) { var renamedPrevArg = ts.factory.createUniqueName(prevArgName.identifier.text, 16 /* GeneratedIdentifierFlags.Optimistic */); return createSynthIdentifier(renamedPrevArg); } function getPossibleNameForVarDecl(node, transformer, continuationArgName) { var possibleNameForVarDecl; // If there is another call in the chain after the .catch() or .finally() we are transforming, we will need to save the result of both paths // (try block and catch/finally 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 continuationArgName and then update the synthNamesMap with a new variable name for // the next transformation step if (continuationArgName && !shouldReturn(node, transformer)) { if (isSynthIdentifier(continuationArgName)) { possibleNameForVarDecl = continuationArgName; transformer.synthNamesMap.forEach(function (val, key) { if (val.identifier.text === continuationArgName.identifier.text) { var newSynthName = createUniqueSynthName(continuationArgName); transformer.synthNamesMap.set(key, newSynthName); } }); } else { possibleNameForVarDecl = createSynthIdentifier(ts.factory.createUniqueName("result", 16 /* GeneratedIdentifierFlags.Optimistic */), continuationArgName.types); } // We are about to write a 'let' variable declaration, but `transformExpression` for both // the try block and catch/finally block will assign to this name. Setting this flag indicates // that future assignments should be written as `name = value` instead of `const name = value`. declareSynthIdentifier(possibleNameForVarDecl); } return possibleNameForVarDecl; } function finishCatchOrFinallyTransform(node, transformer, tryStatement, possibleNameForVarDecl, continuationArgName) { var statements = []; // 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 varDeclIdentifier; if (possibleNameForVarDecl && !shouldReturn(node, transformer)) { varDeclIdentifier = ts.getSynthesizedDeepClone(declareSynthIdentifier(possibleNameForVarDecl)); var typeArray = possibleNameForVarDecl.types; var unionType = transformer.checker.getUnionType(typeArray, 2 /* UnionReduction.Subtype */); var unionTypeNode = transformer.isInJSFile ? undefined : transformer.checker.typeToTypeNode(unionType, /*enclosingDeclaration*/ undefined, /*flags*/ undefined); var varDecl = [ts.factory.createVariableDeclaration(varDeclIdentifier, /*exclamationToken*/ undefined, unionTypeNode)]; var varDeclList = ts.factory.createVariableStatement(/*modifiers*/ undefined, ts.factory.createVariableDeclarationList(varDecl, 1 /* NodeFlags.Let */)); statements.push(varDeclList); } statements.push(tryStatement); if (continuationArgName && varDeclIdentifier && isSynthBindingPattern(continuationArgName)) { statements.push(ts.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ ts.factory.createVariableDeclaration(ts.getSynthesizedDeepClone(declareSynthBindingPattern(continuationArgName)), /*exclamationToken*/ undefined, /*type*/ undefined, varDeclIdentifier) ], 2 /* NodeFlags.Const */))); } return statements; } /** * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows this continuation. * @param continuationArgName The argument name for the continuation that follows this call. */ function transformFinally(node, onFinally, transformer, hasContinuation, continuationArgName) { if (!onFinally || isNullOrUndefined(transformer, onFinally)) { // Ignore this call as it has no effect on the result return transformExpression(/* returnContextNode */ node, node.expression.expression, transformer, hasContinuation, continuationArgName); } var possibleNameForVarDecl = getPossibleNameForVarDecl(node, transformer, continuationArgName); // Transform the left-hand-side of `.finally` into an array of inlined statements. We pass `true` for hasContinuation as `node` is the outer continuation. var inlinedLeftHandSide = transformExpression(/*returnContextNode*/ node, node.expression.expression, transformer, /*hasContinuation*/ true, possibleNameForVarDecl); if (hasFailed()) return silentFail(); // shortcut out of more work // Transform the callback argument into an array of inlined statements. We pass whether we have an outer continuation here // as that indicates whether `return` is valid. var inlinedCallback = transformCallbackArgument(onFinally, hasContinuation, /*continuationArgName*/ undefined, /*argName*/ undefined, node, transformer); if (hasFailed()) return silentFail(); // shortcut out of more work var tryBlock = ts.factory.createBlock(inlinedLeftHandSide); var finallyBlock = ts.factory.createBlock(inlinedCallback); var tryStatement = ts.factory.createTryStatement(tryBlock, /*catchClause*/ undefined, finallyBlock); return finishCatchOrFinallyTransform(node, transformer, tryStatement, possibleNameForVarDecl, continuationArgName); } /** * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows this continuation. * @param continuationArgName The argument name for the continuation that follows this call. */ function transformCatch(node, onRejected, transformer, hasContinuation, continuationArgName) { if (!onRejected || isNullOrUndefined(transformer, onRejected)) { // Ignore this call as it has no effect on the result return transformExpression(/* returnContextNode */ node, node.expression.expression, transformer, hasContinuation, continuationArgName); } var inputArgName = getArgBindingName(onRejected, transformer); var possibleNameForVarDecl = getPossibleNameForVarDecl(node, transformer, continuationArgName); // Transform the left-hand-side of `.then`/`.catch` into an array of inlined statements. We pass `true` for hasContinuation as `node` is the outer continuation. var inlinedLeftHandSide = transformExpression(/*returnContextNode*/ node, node.expression.expression, transformer, /*hasContinuation*/ true, possibleNameForVarDecl); if (hasFailed()) return silentFail(); // shortcut out of more work // Transform the callback argument into an array of inlined statements. We pass whether we have an outer continuation here // as that indicates whether `return` is valid. var inlinedCallback = transformCallbackArgument(onRejected, hasContinuation, possibleNameForVarDecl, inputArgName, node, transformer); if (hasFailed()) return silentFail(); // shortcut out of more work var tryBlock = ts.factory.createBlock(inlinedLeftHandSide); var catchClause = ts.factory.createCatchClause(inputArgName && ts.getSynthesizedDeepClone(declareSynthBindingName(inputArgName)), ts.factory.createBlock(inlinedCallback)); var tryStatement = ts.factory.createTryStatement(tryBlock, catchClause, /*finallyBlock*/ undefined); return finishCatchOrFinallyTransform(node, transformer, tryStatement, possibleNameForVarDecl, continuationArgName); } /** * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows this continuation. * @param continuationArgName The argument name for the continuation that follows this call. */ function transformThen(node, onFulfilled, onRejected, transformer, hasContinuation, continuationArgName) { if (!onFulfilled || isNullOrUndefined(transformer, onFulfilled)) { // If we don't have an `onfulfilled` callback, try treating this as a `.catch`. return transformCatch(node, onRejected, transformer, hasContinuation, continuationArgName); } // We don't currently support transforming a `.then` with both onfulfilled and onrejected handlers, per GH#38152. if (onRejected && !isNullOrUndefined(transformer, onRejected)) { return silentFail(); } var inputArgName = getArgBindingName(onFulfilled, transformer); // Transform the left-hand-side of `.then` into an array of inlined statements. We pass `true` for hasContinuation as `node` is the outer continuation. var inlinedLeftHandSide = transformExpression(node.expression.expression, node.expression.expression, transformer, /*hasContinuation*/ true, inputArgName); if (hasFailed()) return silentFail(); // shortcut out of more work // Transform the callback argument into an array of inlined statements. We pass whether we have an outer continuation here // as that indicates whether `return` is valid. var inlinedCallback = transformCallbackArgument(onFulfilled, hasContinuation, continuationArgName, inputArgName, node, transformer); if (hasFailed()) return silentFail(); // shortcut out of more work return ts.concatenate(inlinedLeftHandSide, inlinedCallback); } /** * Transforms the 'x' part of `x.then(...)`, or the 'y()' part of `y().catch(...)`, where 'x' and 'y()' are Promises. */ function transformPromiseExpressionOfPropertyAccess(returnContextNode, node, transformer, hasContinuation, continuationArgName) { if (shouldReturn(returnContextNode, transformer)) { var returnValue = ts.getSynthesizedDeepClone(node); if (hasContinuation) { returnValue = ts.factory.createAwaitExpression(returnValue); } return [ts.factory.createReturnStatement(returnValue)]; } return createVariableOrAssignmentOrExpressionStatement(continuationArgName, ts.factory.createAwaitExpression(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.factory.createExpressionStatement(rightHandSide)]; } if (isSynthIdentifier(variableName) && variableName.hasBeenDeclared) { // if the variable has already been declared, we don't need "let" or "const" return [ts.factory.createExpressionStatement(ts.factory.createAssignment(ts.getSynthesizedDeepClone(referenceSynthIdentifier(variableName)), rightHandSide))]; } return [ ts.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ ts.factory.createVariableDeclaration(ts.getSynthesizedDeepClone(declareSynthBindingName(variableName)), /*exclamationToken*/ undefined, typeAnnotation, rightHandSide) ], 2 /* NodeFlags.Const */)) ]; } function maybeAnnotateAndReturn(expressionToReturn, typeAnnotation) { if (typeAnnotation && expressionToReturn) { var name = ts.factory.createUniqueName("result", 16 /* GeneratedIdentifierFlags.Optimistic */); return __spreadArray(__spreadArray([], createVariableOrAssignmentOrExpressionStatement(createSynthIdentifier(name), expressionToReturn, typeAnnotation), true), [ ts.factory.createReturnStatement(name) ], false); } return [ts.factory.createReturnStatement(expressionToReturn)]; } // should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts /** * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows the continuation to which this callback belongs. * @param continuationArgName The argument name for the continuation that follows this call. * @param inputArgName The argument name provided to this call */ function transformCallbackArgument(func, hasContinuation, continuationArgName, inputArgName, parent, transformer) { var _a; switch (func.kind) { case 104 /* SyntaxKind.NullKeyword */: // do not produce a transformed statement for a null argument break; case 206 /* SyntaxKind.PropertyAccessExpression */: case 79 /* SyntaxKind.Identifier */: // identifier includes undefined if (!inputArgName) { // undefined was argument passed to promise handler break; } var synthCall = ts.factory.createCallExpression(ts.getSynthesizedDeepClone(func), /*typeArguments*/ undefined, isSynthIdentifier(inputArgName) ? [referenceSynthIdentifier(inputArgName)] : []); if (shouldReturn(parent, transformer)) { return maybeAnnotateAndReturn(synthCall, getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker)); } var type = transformer.checker.getTypeAtLocation(func); var callSignatures = transformer.checker.getSignaturesOfType(type, 0 /* SignatureKind.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(continuationArgName, ts.factory.createAwaitExpression(synthCall), getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker)); if (continuationArgName) { continuationArgName.types.push(transformer.checker.getAwaitedType(returnType) || returnType); } return varDeclOrAssignment; case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: { var funcBody = func.body; var returnType_1 = (_a = getLastCallSignature(transformer.checker.getTypeAtLocation(func), transformer.checker)) === null || _a === void 0 ? void 0 : _a.getReturnType(); // Arrow functions with block bodies { } will enter this control flow if (ts.isBlock(funcBody)) { var refactoredStmts = []; var seenReturnStatement = false; for (var _i = 0, _b = funcBody.statements; _i < _b.length; _i++) { var statement = _b[_i]; if (ts.isReturnStatement(statement)) { seenReturnStatement = true; if (ts.isReturnStatementWithFixablePromiseHandler(statement, transformer.checker)) { refactoredStmts = refactoredStmts.concat(transformReturnStatementWithFixablePromiseHandler(transformer, statement, hasContinuation, continuationArgName)); } else { var possiblyAwaitedRightHandSide = returnType_1 && statement.expression ? getPossiblyAwaitedRightHandSide(transformer.checker, returnType_1, statement.expression) : statement.expression; refactoredStmts.push.apply(refactoredStmts, maybeAnnotateAndReturn(possiblyAwaitedRightHandSide, getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker))); } } else if (hasContinuation && ts.forEachReturnStatement(statement, ts.returnTrue)) { // If there is a nested `return` in a callback that has a trailing continuation, we don't transform it as the resulting complexity is too great. For example: // // source | result // -------------------------------------| --------------------------------------- // function f(): Promise { | async function f9(): Promise { // return foo().then(() => { | await foo(); // if (Math.random()) { | if (Math.random()) { // return 1; | return 1; // incorrect early return // } | } // return 2; | return 2; // incorrect early return // }).then(a => { | const a = undefined; // return a + 1; | return a + 1; // }); | } // } | // // However, branching returns in the outermost continuation are acceptable as no other continuation follows it: // // source | result //--------------------------------------|--------------------------------------- // function f() { | async function f() { // return foo().then(res => { | const res = await foo(); // if (res.ok) { | if (res.ok) { // return 1; | return 1; // } | } // else { | else { // if (res.buffer.length > 5) { | if (res.buffer.length > 5) { // return 2; | return 2; // } | } // else { | else { // return 3; | return 3; // } | } // } | } // }); | } // } | // // We may improve this in the future, but for now the heuristics are too complex return silentFail(); } else { refactoredStmts.push(statement); } } return shouldReturn(parent, transformer) ? refactoredStmts.map(function (s) { return ts.getSynthesizedDeepClone(s); }) : removeReturns(refactoredStmts, continuationArgName, transformer, seenReturnStatement); } else { var inlinedStatements = ts.isFixablePromiseHandler(funcBody, transformer.checker) ? transformReturnStatementWithFixablePromiseHandler(transformer, ts.factory.createReturnStatement(funcBody), hasContinuation, continuationArgName) : ts.emptyArray; if (inlinedStatements.length > 0) { return inlinedStatements; } if (returnType_1) { var possiblyAwaitedRightHandSide = getPossiblyAwaitedRightHandSide(transformer.checker, returnType_1, funcBody); if (!shouldReturn(parent, transformer)) { var transformedStatement = createVariableOrAssignmentOrExpressionStatement(continuationArgName, possiblyAwaitedRightHandSide, /*typeAnnotation*/ undefined); if (continuationArgName) { continuationArgName.types.push(transformer.checker.getAwaitedType(returnType_1) || returnType_1); } return transformedStatement; } else { return maybeAnnotateAndReturn(possiblyAwaitedRightHandSide, getExplicitPromisedTypeOfPromiseReturningCallExpression(parent, func, transformer.checker)); } } else { return silentFail(); } } } 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 getPossiblyAwaitedRightHandSide(checker, type, expr) { var rightHandSide = ts.getSynthesizedDeepClone(expr); return !!checker.getPromisedTypeOfPromise(type) ? ts.factory.createAwaitExpression(rightHandSide) : rightHandSide; } function getLastCallSignature(type, checker) { var callSignatures = checker.getSignaturesOfType(type, 0 /* SignatureKind.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.factory.createAwaitExpression(stmt.expression) : stmt.expression; if (prevArgName === undefined) { ret.push(ts.factory.createExpressionStatement(possiblyAwaitedExpression)); } else if (isSynthIdentifier(prevArgName) && prevArgName.hasBeenDeclared) { ret.push(ts.factory.createExpressionStatement(ts.factory.createAssignment(referenceSynthIdentifier(prevArgName), possiblyAwaitedExpression))); } else { ret.push(ts.factory.createVariableStatement(/*modifiers*/ undefined, (ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(declareSynthBindingName(prevArgName), /*exclamationToken*/ undefined, /*type*/ undefined, possiblyAwaitedExpression)], 2 /* NodeFlags.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.factory.createVariableStatement(/*modifiers*/ undefined, (ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(declareSynthBindingName(prevArgName), /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createIdentifier("undefined"))], 2 /* NodeFlags.Const */)))); } return ret; } /** * @param hasContinuation Whether another `then`, `catch`, or `finally` continuation follows the continuation to which this statement belongs. * @param continuationArgName The argument name for the continuation that follows this call. */ function transformReturnStatementWithFixablePromiseHandler(transformer, innerRetStmt, hasContinuation, continuationArgName) { var innerCbBody = []; ts.forEachChild(innerRetStmt, function visit(node) { if (ts.isCallExpression(node)) { var temp = transformExpression(node, node, transformer, hasContinuation, continuationArgName); 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); } else if (ts.isPropertyAccessExpression(funcNode) && ts.isIdentifier(funcNode.name)) { name = getMapEntryOrDefault(funcNode.name); } // 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 createSynthIdentifier(identifier, types) { if (types === void 0) { types = []; } return { kind: 0 /* SynthBindingNameKind.Identifier */, identifier: identifier, types: types, hasBeenDeclared: false, hasBeenReferenced: false }; } function createSynthBindingPattern(bindingPattern, elements, types) { if (elements === void 0) { elements = ts.emptyArray; } if (types === void 0) { types = []; } return { kind: 1 /* SynthBindingNameKind.BindingPattern */, bindingPattern: bindingPattern, elements: elements, types: types }; } function referenceSynthIdentifier(synthId) { synthId.hasBeenReferenced = true; return synthId.identifier; } function declareSynthBindingName(synthName) { return isSynthIdentifier(synthName) ? declareSynthIdentifier(synthName) : declareSynthBindingPattern(synthName); } function declareSynthBindingPattern(synthPattern) { for (var _i = 0, _a = synthPattern.elements; _i < _a.length; _i++) { var element = _a[_i]; declareSynthBindingName(element); } return synthPattern.bindingPattern; } function declareSynthIdentifier(synthId) { synthId.hasBeenDeclared = true; return synthId.identifier; } function isSynthIdentifier(bindingName) { return bindingName.kind === 0 /* SynthBindingNameKind.Identifier */; } function isSynthBindingPattern(bindingName) { return bindingName.kind === 1 /* SynthBindingNameKind.BindingPattern */; } function shouldReturn(expression, transformer) { return !!expression.original && transformer.setOfExpressionsToReturn.has(ts.getNodeId(expression.original)); } })(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_ES_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 = convertFileToEsModule(sourceFile, program.getTypeChecker(), changes, ts.getEmitScriptTarget(program.getCompilerOptions()), 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("convertToEsModule", changes, ts.Diagnostics.Convert_to_ES_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, ts.getModeForUsageLocation(importingFile, moduleSpecifier)); if (!imported || imported.resolvedFileName !== exportingFile.fileName) { continue; } var importNode = ts.importFromModuleSpecifier(moduleSpecifier); switch (importNode.kind) { case 265 /* SyntaxKind.ImportEqualsDeclaration */: changes.replaceNode(importingFile, importNode, ts.makeImport(importNode.name, /*namedImports*/ undefined, moduleSpecifier, quotePreference)); break; case 208 /* SyntaxKind.CallExpression */: if (ts.isRequireCall(importNode, /*checkArgumentIsStringLiteralLike*/ false)) { changes.replaceNode(importingFile, importNode, ts.factory.createPropertyAccessExpression(ts.getSynthesizedDeepClone(importNode), "default")); } break; } } } /** @returns Whether we converted a `module.exports =` to a default export. */ function convertFileToEsModule(sourceFile, checker, changes, target, quotePreference) { var identifiers = { original: collectFreeIdentifiers(sourceFile), additional: new ts.Set() }; var exports = collectExportRenames(sourceFile, checker, identifiers); convertExportsAccesses(sourceFile, exports, changes); var moduleExportsChangedToDefault = false; var useSitesToUnqualify; // Process variable statements first to collect use sites that need to be updated inside other transformations for (var _i = 0, _a = ts.filter(sourceFile.statements, ts.isVariableStatement); _i < _a.length; _i++) { var statement = _a[_i]; var newUseSites = convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target, quotePreference); if (newUseSites) { ts.copyEntries(newUseSites, useSitesToUnqualify !== null && useSitesToUnqualify !== void 0 ? useSitesToUnqualify : (useSitesToUnqualify = new ts.Map())); } } // `convertStatement` will delete entries from `useSitesToUnqualify` when containing statements are replaced for (var _b = 0, _c = ts.filter(sourceFile.statements, function (s) { return !ts.isVariableStatement(s); }); _b < _c.length; _b++) { var statement = _c[_b]; var moduleExportsChanged = convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, useSitesToUnqualify, quotePreference); moduleExportsChangedToDefault = moduleExportsChangedToDefault || moduleExportsChanged; } // Remaining use sites can be changed directly useSitesToUnqualify === null || useSitesToUnqualify === void 0 ? void 0 : useSitesToUnqualify.forEach(function (replacement, original) { changes.replaceNode(sourceFile, original, replacement); }); return moduleExportsChangedToDefault; } function collectExportRenames(sourceFile, checker, identifiers) { var res = new ts.Map(); 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 /* SymbolFlags.Value */, /*excludeGlobals*/ true))) { // Unconditionally add an underscore in case `text` is a keyword. res.set(text, makeUniqueName("_".concat(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.factory.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 === 63 /* SyntaxKind.EqualsToken */); } node.forEachChild(recur); }); } function convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports, useSitesToUnqualify, quotePreference) { switch (statement.kind) { case 237 /* SyntaxKind.VariableStatement */: convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target, quotePreference); return false; case 238 /* SyntaxKind.ExpressionStatement */: { var expression = statement.expression; switch (expression.kind) { case 208 /* SyntaxKind.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 221 /* SyntaxKind.BinaryExpression */: { var operatorToken = expression.operatorToken; return operatorToken.kind === 63 /* SyntaxKind.EqualsToken */ && convertAssignment(sourceFile, checker, expression, changes, exports, useSitesToUnqualify); } } } // falls through default: return false; } } function convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target, quotePreference) { var declarationList = statement.declarationList; var foundImport = false; var converted = ts.map(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 convertedImports([]); } else if (ts.isRequireCall(initializer, /*checkArgumentIsStringLiteralLike*/ true)) { foundImport = true; return convertSingleImport(name, initializer.arguments[0], 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 convertedImports([ts.factory.createVariableStatement(/*modifiers*/ undefined, ts.factory.createVariableDeclarationList([decl], declarationList.flags))]); }); if (foundImport) { // useNonAdjustedEndPosition to ensure we don't eat the newline after the statement. changes.replaceNodeWithNodes(sourceFile, statement, ts.flatMap(converted, function (c) { return c.newImports; })); var combinedUseSites_1; ts.forEach(converted, function (c) { if (c.useSitesToUnqualify) { ts.copyEntries(c.useSitesToUnqualify, combinedUseSites_1 !== null && combinedUseSites_1 !== void 0 ? combinedUseSites_1 : (combinedUseSites_1 = new ts.Map())); } }); return combinedUseSites_1; } } /** Converts `const name = require("moduleSpecifier").propertyName` */ function convertPropertyAccessImport(name, propertyName, moduleSpecifier, identifiers, quotePreference) { switch (name.kind) { case 201 /* SyntaxKind.ObjectBindingPattern */: case 202 /* SyntaxKind.ArrayBindingPattern */: { // `const [a, b] = require("c").d` --> `import { d } from "c"; const [a, b] = d;` var tmp = makeUniqueName(propertyName, identifiers); return convertedImports([ makeSingleImport(tmp, propertyName, moduleSpecifier, quotePreference), makeConst(/*modifiers*/ undefined, name, ts.factory.createIdentifier(tmp)), ]); } case 79 /* SyntaxKind.Identifier */: // `const a = require("b").c` --> `import { c as a } from "./b"; return convertedImports([makeSingleImport(name.text, propertyName, moduleSpecifier, quotePreference)]); default: return ts.Debug.assertNever(name, "Convert to ES module got invalid syntax form ".concat(name.kind)); } } function convertAssignment(sourceFile, checker, assignment, changes, exports, useSitesToUnqualify) { 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, useSitesToUnqualify) : 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, useSitesToUnqualify) { var statements = ts.mapAllOrFail(object.properties, function (prop) { switch (prop.kind) { case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: // TODO: Maybe we should handle this? See fourslash test `refactorConvertToEs6Module_export_object_shorthand.ts`. // falls through case 297 /* SyntaxKind.ShorthandPropertyAssignment */: case 298 /* SyntaxKind.SpreadAssignment */: return undefined; case 296 /* SyntaxKind.PropertyAssignment */: return !ts.isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer, useSitesToUnqualify); case 169 /* SyntaxKind.MethodDeclaration */: return !ts.isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [ts.factory.createToken(93 /* SyntaxKind.ExportKeyword */)], prop, useSitesToUnqualify); default: ts.Debug.assertNever(prop, "Convert to ES6 got invalid prop kind ".concat(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.factory.createExportSpecifier(/*isTypeOnly*/ false, 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.emptyMap; return exports.has("export=" /* InternalSymbolName.ExportEquals */) ? [[reExportDefault(moduleSpecifier)], true] : !exports.has("default" /* InternalSymbolName.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.factory.createExportSpecifier(/*isTypeOnly*/ false, /*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.factory.createToken(93 /* SyntaxKind.ExportKeyword */), { suffix: " " }); if (!right.name) changes.insertName(sourceFile, right, name); var semi = ts.findChildOfKind(parent, 26 /* SyntaxKind.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 /* SyntaxKind.DotToken */, sourceFile), [ts.factory.createToken(93 /* SyntaxKind.ExportKeyword */), ts.factory.createToken(85 /* SyntaxKind.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, useSitesToUnqualify) { var modifiers = [ts.factory.createToken(93 /* SyntaxKind.ExportKeyword */)]; switch (exported.kind) { case 213 /* SyntaxKind.FunctionExpression */: { var expressionName = exported.name; if (expressionName && expressionName.text !== name) { // `exports.f = function g() {}` -> `export const f = function g() {}` return exportConst(); } } // falls through case 214 /* SyntaxKind.ArrowFunction */: // `exports.f = function() {}` --> `export function f() {}` return functionExpressionToDeclaration(name, modifiers, exported, useSitesToUnqualify); case 226 /* SyntaxKind.ClassExpression */: // `exports.C = class {}` --> `export class C {}` return classExpressionToDeclaration(name, modifiers, exported, useSitesToUnqualify); default: return exportConst(); } function exportConst() { // `exports.x = 0;` --> `export const x = 0;` return makeConst(modifiers, ts.factory.createIdentifier(name), replaceImportUseSites(exported, useSitesToUnqualify)); // TODO: GH#18217 } } function replaceImportUseSites(nodeOrNodes, useSitesToUnqualify) { if (!useSitesToUnqualify || !ts.some(ts.arrayFrom(useSitesToUnqualify.keys()), function (original) { return ts.rangeContainsRange(nodeOrNodes, original); })) { return nodeOrNodes; } return ts.isArray(nodeOrNodes) ? ts.getSynthesizedDeepClonesWithReplacements(nodeOrNodes, /*includeTrivia*/ true, replaceNode) : ts.getSynthesizedDeepCloneWithReplacements(nodeOrNodes, /*includeTrivia*/ true, replaceNode); function replaceNode(original) { // We are replacing `mod.SomeExport` wih `SomeExport`, so we only need to look at PropertyAccessExpressions if (original.kind === 206 /* SyntaxKind.PropertyAccessExpression */) { var replacement = useSitesToUnqualify.get(original); // Remove entry from `useSitesToUnqualify` so the refactor knows it's taken care of by the parent statement we're replacing useSitesToUnqualify.delete(original); return replacement; } } } /** * 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(name, moduleSpecifier, checker, identifiers, target, quotePreference) { switch (name.kind) { case 201 /* SyntaxKind.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 : makeImportSpecifier(e.propertyName && e.propertyName.text, e.name.text); }); if (importSpecifiers) { return convertedImports([ts.makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier, quotePreference)]); } } // falls through -- object destructuring has an interesting pattern and must be a variable declaration case 202 /* SyntaxKind.ArrayBindingPattern */: { /* import x from "x"; const [a, b, c] = x; */ var tmp = makeUniqueName(codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, target), identifiers); return convertedImports([ ts.makeImport(ts.factory.createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference), makeConst(/*modifiers*/ undefined, ts.getSynthesizedDeepClone(name), ts.factory.createIdentifier(tmp)), ]); } case 79 /* SyntaxKind.Identifier */: return convertSingleIdentifierImport(name, moduleSpecifier, checker, identifiers, quotePreference); default: return ts.Debug.assertNever(name, "Convert to ES module got invalid name kind ".concat(name.kind)); } } /** * Convert `import x = require("x").` * Also: * - Convert `x.default()` to `x()` to handle ES6 default export * - Converts uses like `x.y()` to `y()` and uses a named import. */ function convertSingleIdentifierImport(name, moduleSpecifier, 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 = new ts.Map(); // True if there is some non-property use like `x()` or `f(x)`. var needDefaultImport = false; var useSitesToUnqualify; 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 propertyName = parent.name.text; if (propertyName === "default") { needDefaultImport = true; var importDefaultName = use.getText(); (useSitesToUnqualify !== null && useSitesToUnqualify !== void 0 ? useSitesToUnqualify : (useSitesToUnqualify = new ts.Map())).set(parent, ts.factory.createIdentifier(importDefaultName)); } else { ts.Debug.assert(parent.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); } (useSitesToUnqualify !== null && useSitesToUnqualify !== void 0 ? useSitesToUnqualify : (useSitesToUnqualify = new ts.Map())).set(parent, ts.factory.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.factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName === idName ? undefined : ts.factory.createIdentifier(propertyName), ts.factory.createIdentifier(idName)); })); if (!namedBindings) { // If it was unused, ensure that we at least import *something*. needDefaultImport = true; } return convertedImports([ts.makeImport(needDefaultImport ? ts.getSynthesizedDeepClone(name) : undefined, namedBindings, moduleSpecifier, quotePreference)], useSitesToUnqualify); } // Identifiers helpers function makeUniqueName(name, identifiers) { while (identifiers.original.has(name) || identifiers.additional.has(name)) { name = "_".concat(name); } identifiers.additional.add(name); 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 206 /* SyntaxKind.PropertyAccessExpression */: return parent.name !== node; case 203 /* SyntaxKind.BindingElement */: return parent.propertyName !== node; case 270 /* SyntaxKind.ImportSpecifier */: return parent.propertyName !== node; default: return true; } } // Node helpers function functionExpressionToDeclaration(name, additionalModifiers, fn, useSitesToUnqualify) { return ts.factory.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.factory.converters.convertToFunctionBlock(replaceImportUseSites(fn.body, useSitesToUnqualify))); } function classExpressionToDeclaration(name, additionalModifiers, cls, useSitesToUnqualify) { return ts.factory.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), replaceImportUseSites(cls.members, useSitesToUnqualify)); } function makeSingleImport(localName, propertyName, moduleSpecifier, quotePreference) { return propertyName === "default" ? ts.makeImport(ts.factory.createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference) : ts.makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference); } function makeImportSpecifier(propertyName, name) { return ts.factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName !== undefined && propertyName !== name ? ts.factory.createIdentifier(propertyName) : undefined, ts.factory.createIdentifier(name)); } function makeConst(modifiers, name, init) { return ts.factory.createVariableStatement(modifiers, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, /*type*/ undefined, init)], 2 /* NodeFlags.Const */)); } function makeExportDeclaration(exportSpecifiers, moduleSpecifier) { return ts.factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, exportSpecifiers && ts.factory.createNamedExports(exportSpecifiers), moduleSpecifier === undefined ? undefined : ts.factory.createStringLiteral(moduleSpecifier)); } function convertedImports(newImports, useSitesToUnqualify) { return { newImports: newImports, useSitesToUnqualify: useSitesToUnqualify }; } })(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 = "".concat(qualifiedName.left.text, "[\"").concat(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.factory.createIndexedAccessTypeNode(ts.factory.createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined), ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(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 getCodeActionsToConvertToTypeOnlyExport(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 getAllCodeActionsToConvertToTypeOnlyExport(context) { var fixedExportDeclarations = new ts.Map(); 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.insertModifierBefore(context.sourceFile, 152 /* SyntaxKind.TypeKeyword */, exportClause); } else { var valueExportDeclaration = ts.factory.updateExportDeclaration(exportDeclaration, exportDeclaration.decorators, exportDeclaration.modifiers, /*isTypeOnly*/ false, ts.factory.updateNamedExports(exportClause, ts.filter(exportClause.elements, function (e) { return !ts.contains(typeExportSpecifiers, e); })), exportDeclaration.moduleSpecifier, /*assertClause*/ undefined); var typeExportDeclaration = ts.factory.createExportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ true, ts.factory.createNamedExports(typeExportSpecifiers), exportDeclaration.moduleSpecifier, /*assertClause*/ undefined); changes.replaceNode(context.sourceFile, exportDeclaration, valueExportDeclaration, { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); 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_importsNotUsedAsValues_is_set_to_error.code]; var fixId = "convertToTypeOnlyImport"; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function getCodeActionsToConvertToTypeOnlyImport(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 getAllCodeActionsToConvertToTypeOnlyImport(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.factory.updateImportDeclaration(importDeclaration, /*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createImportClause( /*isTypeOnly*/ true, importClause.name, /*namedBindings*/ undefined), importDeclaration.moduleSpecifier, /*assertClause*/ undefined)); } } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixId = "convertLiteralTypeToMappedType"; var errorCodes = [ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0.code]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function getCodeActionsToConvertLiteralTypeToMappedType(context) { var sourceFile = context.sourceFile, span = context.span; var info = getInfo(sourceFile, span.start); if (!info) { return undefined; } var name = info.name, constraint = info.constraint; var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, info); }); return [codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Convert_0_to_1_in_0, constraint, name], fixId, ts.Diagnostics.Convert_all_type_literals_to_mapped_type)]; }, 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); if (ts.isIdentifier(token)) { var propertySignature = ts.cast(token.parent.parent, ts.isPropertySignature); var propertyName = token.getText(sourceFile); return { container: ts.cast(propertySignature.parent, ts.isTypeLiteralNode), typeNode: propertySignature.type, constraint: propertyName, name: propertyName === "K" ? "P" : "K", }; } return undefined; } function doChange(changes, sourceFile, _a) { var container = _a.container, typeNode = _a.typeNode, constraint = _a.constraint, name = _a.name; changes.replaceNode(sourceFile, container, ts.factory.createMappedTypeNode( /*readonlyToken*/ undefined, ts.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, ts.factory.createTypeReferenceNode(constraint)), /*nameType*/ undefined, /*questionToken*/ undefined, typeNode, /*members*/ undefined)); } })(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 = new ts.Map(); 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.getEffectiveModifierFlags(symbol.valueDeclaration) & 8 /* ModifierFlags.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 /* IndexKind.Number */); } if (!classType.getStringIndexType()) { createMissingIndexSignatureDeclaration(implementedType, 0 /* IndexKind.String */); } var importAdder = codefix.createImportAdder(sourceFile, context.program, preferences, context.host); codefix.createMissingMemberNodes(classDeclaration, nonPrivateAndNotExistedInHeritageClauseMembers, sourceFile, 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, 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.insertMemberAtStart(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, ts.Diagnostics.No_value_exists_in_scope_for_the_shorthand_property_0_Either_declare_one_or_provide_an_initializer.code, ts.Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var errorCode = context.errorCode, preferences = context.preferences, sourceFile = context.sourceFile, span = context.span, program = context.program; var info = getFixesInfo(context, errorCode, span.start, /*useAutoImportProvider*/ true); if (!info) return undefined; var fixes = info.fixes, symbolName = info.symbolName, errorIdentifierText = info.errorIdentifierText; var quotePreference = ts.getQuotePreference(sourceFile, preferences); return fixes.map(function (fix) { return codeActionForFix(context, sourceFile, symbolName, fix, /*includeSymbolNameInDescription*/ symbolName !== errorIdentifierText, quotePreference, program.getCompilerOptions()); }); }, fixIds: [importFixId], getAllCodeActions: function (context) { var sourceFile = context.sourceFile, program = context.program, preferences = context.preferences, host = context.host; var importAdder = createImportAdderWorker(sourceFile, program, /*useAutoImportProvider*/ true, 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) { return createImportAdderWorker(sourceFile, program, /*useAutoImportProvider*/ false, preferences, host); } codefix.createImportAdder = createImportAdder; function createImportAdderWorker(sourceFile, program, useAutoImportProvider, 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 = new ts.Map(); /** Use `getNewImportEntry` for access */ var newImports = new ts.Map(); return { addImportFromDiagnostic: addImportFromDiagnostic, addImportFromExportedSymbol: addImportFromExportedSymbol, writeFixes: writeFixes, hasFixes: hasFixes }; function addImportFromDiagnostic(diagnostic, context) { var info = getFixesInfo(context, diagnostic.code, diagnostic.start, useAutoImportProvider); if (!info || !info.fixes.length) return; addImport(info); } function addImportFromExportedSymbol(exportedSymbol, isValidTypeOnlyUseSite) { 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 exportInfo = getAllReExportingModules(sourceFile, symbol, moduleSymbol, symbolName, /*isJsxTagName*/ false, host, program, preferences, useAutoImportProvider); var useRequire = shouldUseRequire(sourceFile, program); var fix = getImportFixForSymbol(sourceFile, exportInfo, moduleSymbol, program, /*useNamespaceInfo*/ undefined, !!isValidTypeOnlyUseSite, useRequire, host, preferences); if (fix) { addImport({ fixes: [fix], symbolName: symbolName, errorIdentifierText: undefined }); } } function addImport(info) { var _a, _b; var fixes = info.fixes, symbolName = info.symbolName; var fix = ts.first(fixes); switch (fix.kind) { case 0 /* ImportFixKind.UseNamespace */: addToNamespace.push(fix); break; case 1 /* ImportFixKind.JsdocTypeImport */: importType.push(fix); break; case 2 /* ImportFixKind.AddToExisting */: { var importClauseOrBindingPattern = fix.importClauseOrBindingPattern, importKind = fix.importKind, addAsTypeOnly = fix.addAsTypeOnly; var key = String(ts.getNodeId(importClauseOrBindingPattern)); var entry = addToExisting.get(key); if (!entry) { addToExisting.set(key, entry = { importClauseOrBindingPattern: importClauseOrBindingPattern, defaultImport: undefined, namedImports: new ts.Map() }); } if (importKind === 0 /* ImportKind.Named */) { var prevValue = entry === null || entry === void 0 ? void 0 : entry.namedImports.get(symbolName); entry.namedImports.set(symbolName, reduceAddAsTypeOnlyValues(prevValue, addAsTypeOnly)); } else { ts.Debug.assert(entry.defaultImport === undefined || entry.defaultImport.name === symbolName, "(Add to Existing) Default import should be missing or match symbolName"); entry.defaultImport = { name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues((_a = entry.defaultImport) === null || _a === void 0 ? void 0 : _a.addAsTypeOnly, addAsTypeOnly), }; } break; } case 3 /* ImportFixKind.AddNew */: { var moduleSpecifier = fix.moduleSpecifier, importKind = fix.importKind, useRequire = fix.useRequire, addAsTypeOnly = fix.addAsTypeOnly; var entry = getNewImportEntry(moduleSpecifier, importKind, useRequire, addAsTypeOnly); ts.Debug.assert(entry.useRequire === useRequire, "(Add new) Tried to add an `import` and a `require` for the same module"); switch (importKind) { case 1 /* ImportKind.Default */: ts.Debug.assert(entry.defaultImport === undefined || entry.defaultImport.name === symbolName, "(Add new) Default import should be missing or match symbolName"); entry.defaultImport = { name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues((_b = entry.defaultImport) === null || _b === void 0 ? void 0 : _b.addAsTypeOnly, addAsTypeOnly) }; break; case 0 /* ImportKind.Named */: var prevValue = (entry.namedImports || (entry.namedImports = new ts.Map())).get(symbolName); entry.namedImports.set(symbolName, reduceAddAsTypeOnlyValues(prevValue, addAsTypeOnly)); break; case 3 /* ImportKind.CommonJS */: case 2 /* ImportKind.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, addAsTypeOnly: addAsTypeOnly }; break; } break; } case 4 /* ImportFixKind.PromoteTypeOnly */: // Excluding from fix-all break; default: ts.Debug.assertNever(fix, "fix wasn't never - got kind ".concat(fix.kind)); } function reduceAddAsTypeOnlyValues(prevValue, newValue) { // `NotAllowed` overrides `Required` because one addition of a new import might be required to be type-only // because of `--importsNotUsedAsValues=error`, but if a second addition of the same import is `NotAllowed` // to be type-only, the reason the first one was `Required` - the unused runtime dependency - is now moot. // Alternatively, if one addition is `Required` because it has no value meaning under `--preserveValueImports` // and `--isolatedModules`, it should be impossible for another addition to be `NotAllowed` since that would // mean a type is being referenced in a value location. return Math.max(prevValue !== null && prevValue !== void 0 ? prevValue : 0, newValue); } function getNewImportEntry(moduleSpecifier, importKind, useRequire, addAsTypeOnly) { // A default import that requires type-only makes the whole import type-only. // (We could add `default` as a named import, but that style seems undesirable.) // Under `--preserveValueImports` and `--importsNotUsedAsValues=error`, if a // module default-exports a type but named-exports some values (weird), you would // have to use a type-only default import and non-type-only named imports. These // require two separate import declarations, so we build this into the map key. var typeOnlyKey = newImportsKey(moduleSpecifier, /*topLevelTypeOnly*/ true); var nonTypeOnlyKey = newImportsKey(moduleSpecifier, /*topLevelTypeOnly*/ false); var typeOnlyEntry = newImports.get(typeOnlyKey); var nonTypeOnlyEntry = newImports.get(nonTypeOnlyKey); var newEntry = { defaultImport: undefined, namedImports: undefined, namespaceLikeImport: undefined, useRequire: useRequire }; if (importKind === 1 /* ImportKind.Default */ && addAsTypeOnly === 2 /* AddAsTypeOnly.Required */) { if (typeOnlyEntry) return typeOnlyEntry; newImports.set(typeOnlyKey, newEntry); return newEntry; } if (addAsTypeOnly === 1 /* AddAsTypeOnly.Allowed */ && (typeOnlyEntry || nonTypeOnlyEntry)) { return (typeOnlyEntry || nonTypeOnlyEntry); } if (nonTypeOnlyEntry) { return nonTypeOnlyEntry; } newImports.set(nonTypeOnlyKey, newEntry); return newEntry; } function newImportsKey(moduleSpecifier, topLevelTypeOnly) { return "".concat(topLevelTypeOnly ? 1 : 0, "|").concat(moduleSpecifier); } } 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; doAddExistingFix(changeTracker, sourceFile, importClauseOrBindingPattern, defaultImport, ts.arrayFrom(namedImports.entries(), function (_a) { var name = _a[0], addAsTypeOnly = _a[1]; return ({ addAsTypeOnly: addAsTypeOnly, name: name }); }), compilerOptions); }); var newDeclarations; newImports.forEach(function (_a, key) { var useRequire = _a.useRequire, defaultImport = _a.defaultImport, namedImports = _a.namedImports, namespaceLikeImport = _a.namespaceLikeImport; var moduleSpecifier = key.slice(2); // From `${0 | 1}|${moduleSpecifier}` format var getDeclarations = useRequire ? getNewRequires : getNewImports; var declarations = getDeclarations(moduleSpecifier, quotePreference, defaultImport, namedImports && ts.arrayFrom(namedImports.entries(), function (_a) { var name = _a[0], addAsTypeOnly = _a[1]; return ({ addAsTypeOnly: addAsTypeOnly, name: name }); }), namespaceLikeImport); newDeclarations = ts.combine(newDeclarations, declarations); }); if (newDeclarations) { ts.insertImports(changeTracker, sourceFile, newDeclarations, /*blankLineBetween*/ true); } } function hasFixes() { return addToNamespace.length > 0 || importType.length > 0 || addToExisting.size > 0 || newImports.size > 0; } } function createImportSpecifierResolver(importingFile, program, host, preferences) { var packageJsonImportFilter = ts.createPackageJsonImportFilter(importingFile, preferences, host); var importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); return { getModuleSpecifierForBestExportInfo: getModuleSpecifierForBestExportInfo }; function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, fromCacheOnly) { var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, /*useRequire*/ false, program, importingFile, host, preferences, importMap, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter, host); return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); } } codefix.createImportSpecifierResolver = createImportSpecifierResolver; // Sorted with the preferred fix coming first. var ImportFixKind; (function (ImportFixKind) { ImportFixKind[ImportFixKind["UseNamespace"] = 0] = "UseNamespace"; ImportFixKind[ImportFixKind["JsdocTypeImport"] = 1] = "JsdocTypeImport"; ImportFixKind[ImportFixKind["AddToExisting"] = 2] = "AddToExisting"; ImportFixKind[ImportFixKind["AddNew"] = 3] = "AddNew"; ImportFixKind[ImportFixKind["PromoteTypeOnly"] = 4] = "PromoteTypeOnly"; })(ImportFixKind || (ImportFixKind = {})); // These should not be combined as bitflags, but are given powers of 2 values to // easily detect conflicts between `NotAllowed` and `Required` by giving them a unique sum. // They're also ordered in terms of increasing priority for a fix-all scenario (see // `reduceAddAsTypeOnlyValues`). var AddAsTypeOnly; (function (AddAsTypeOnly) { AddAsTypeOnly[AddAsTypeOnly["Allowed"] = 1] = "Allowed"; AddAsTypeOnly[AddAsTypeOnly["Required"] = 2] = "Required"; AddAsTypeOnly[AddAsTypeOnly["NotAllowed"] = 4] = "NotAllowed"; })(AddAsTypeOnly || (AddAsTypeOnly = {})); function getImportCompletionAction(targetSymbol, moduleSymbol, sourceFile, symbolName, isJsxTagName, host, program, formatContext, position, preferences) { var compilerOptions = program.getCompilerOptions(); var exportInfos = ts.pathIsBareSpecifier(ts.stripQuotes(moduleSymbol.name)) ? [getSymbolExportInfoForSymbol(targetSymbol, moduleSymbol, program, host)] : getAllReExportingModules(sourceFile, targetSymbol, moduleSymbol, symbolName, isJsxTagName, host, program, preferences, /*useAutoImportProvider*/ true); var useRequire = shouldUseRequire(sourceFile, program); var isValidTypeOnlyUseSite = ts.isValidTypeOnlyAliasUseSite(ts.getTokenAtPosition(sourceFile, position)); var fix = ts.Debug.checkDefined(getImportFixForSymbol(sourceFile, exportInfos, moduleSymbol, program, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, useRequire, host, preferences)); return { moduleSpecifier: fix.moduleSpecifier, codeAction: codeFixActionToCodeAction(codeActionForFix({ host: host, formatContext: formatContext, preferences: preferences }, sourceFile, symbolName, fix, /*includeSymbolNameInDescription*/ false, ts.getQuotePreference(sourceFile, preferences), compilerOptions)) }; } codefix.getImportCompletionAction = getImportCompletionAction; function getPromoteTypeOnlyCompletionAction(sourceFile, symbolToken, program, host, formatContext, preferences) { var compilerOptions = program.getCompilerOptions(); var symbolName = getSymbolName(sourceFile, program.getTypeChecker(), symbolToken, compilerOptions); var fix = getTypeOnlyPromotionFix(sourceFile, symbolToken, symbolName, program); var includeSymbolNameInDescription = symbolName !== symbolToken.text; return fix && codeFixActionToCodeAction(codeActionForFix({ host: host, formatContext: formatContext, preferences: preferences }, sourceFile, symbolName, fix, includeSymbolNameInDescription, 1 /* QuotePreference.Double */, compilerOptions)); } codefix.getPromoteTypeOnlyCompletionAction = getPromoteTypeOnlyCompletionAction; function getImportFixForSymbol(sourceFile, exportInfos, moduleSymbol, program, useNamespaceInfo, isValidTypeOnlyUseSite, useRequire, host, preferences) { ts.Debug.assert(exportInfos.some(function (info) { return info.moduleSymbol === moduleSymbol || info.symbol.parent === moduleSymbol; }), "Some exportInfo should match the specified moduleSymbol"); var packageJsonImportFilter = ts.createPackageJsonImportFilter(sourceFile, preferences, host); return getBestFix(getImportFixes(exportInfos, useNamespaceInfo, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes, sourceFile, program, packageJsonImportFilter, host); } function codeFixActionToCodeAction(_a) { var description = _a.description, changes = _a.changes, commands = _a.commands; return { description: description, changes: changes, commands: commands }; } function getSymbolExportInfoForSymbol(symbol, moduleSymbol, program, host) { var _a, _b; var compilerOptions = program.getCompilerOptions(); var mainProgramInfo = getInfoWithChecker(program.getTypeChecker(), /*isFromPackageJson*/ false); if (mainProgramInfo) { return mainProgramInfo; } var autoImportProvider = (_b = (_a = host.getPackageJsonAutoImportProvider) === null || _a === void 0 ? void 0 : _a.call(host)) === null || _b === void 0 ? void 0 : _b.getTypeChecker(); return ts.Debug.checkDefined(autoImportProvider && getInfoWithChecker(autoImportProvider, /*isFromPackageJson*/ true), "Could not find symbol in specified module for code actions"); function getInfoWithChecker(checker, isFromPackageJson) { var defaultInfo = ts.getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); if (defaultInfo && ts.skipAlias(defaultInfo.symbol, checker) === symbol) { return { symbol: defaultInfo.symbol, moduleSymbol: moduleSymbol, moduleFileName: undefined, exportKind: defaultInfo.exportKind, targetFlags: ts.skipAlias(symbol, checker).flags, isFromPackageJson: isFromPackageJson }; } var named = checker.tryGetMemberInModuleExportsAndProperties(symbol.name, moduleSymbol); if (named && ts.skipAlias(named, checker) === symbol) { return { symbol: named, moduleSymbol: moduleSymbol, moduleFileName: undefined, exportKind: 0 /* ExportKind.Named */, targetFlags: ts.skipAlias(symbol, checker).flags, isFromPackageJson: isFromPackageJson }; } } } function getAllReExportingModules(importingFile, targetSymbol, exportingModuleSymbol, symbolName, isJsxTagName, host, program, preferences, useAutoImportProvider) { var result = []; var compilerOptions = program.getCompilerOptions(); var getModuleSpecifierResolutionHost = ts.memoizeOne(function (isFromPackageJson) { return ts.createModuleSpecifierResolutionHost(isFromPackageJson ? host.getPackageJsonAutoImportProvider() : program, host); }); ts.forEachExternalModuleToImportFrom(program, host, useAutoImportProvider, function (moduleSymbol, moduleFile, program, isFromPackageJson) { var checker = program.getTypeChecker(); // Don't import from a re-export when looking "up" like to `./index` or `../index`. if (moduleFile && moduleSymbol !== exportingModuleSymbol && ts.startsWith(importingFile.fileName, ts.getDirectoryPath(moduleFile.fileName))) { return; } var defaultInfo = ts.getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); if (defaultInfo && (defaultInfo.name === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, ts.getEmitScriptTarget(compilerOptions), isJsxTagName) === symbolName) && ts.skipAlias(defaultInfo.symbol, checker) === targetSymbol && isImportable(program, moduleFile, isFromPackageJson)) { result.push({ symbol: defaultInfo.symbol, moduleSymbol: moduleSymbol, moduleFileName: moduleFile === null || moduleFile === void 0 ? void 0 : moduleFile.fileName, exportKind: defaultInfo.exportKind, targetFlags: ts.skipAlias(defaultInfo.symbol, checker).flags, isFromPackageJson: isFromPackageJson }); } for (var _i = 0, _a = checker.getExportsAndPropertiesOfModule(moduleSymbol); _i < _a.length; _i++) { var exported = _a[_i]; if (exported.name === symbolName && checker.getMergedSymbol(ts.skipAlias(exported, checker)) === targetSymbol && isImportable(program, moduleFile, isFromPackageJson)) { result.push({ symbol: exported, moduleSymbol: moduleSymbol, moduleFileName: moduleFile === null || moduleFile === void 0 ? void 0 : moduleFile.fileName, exportKind: 0 /* ExportKind.Named */, targetFlags: ts.skipAlias(exported, checker).flags, isFromPackageJson: isFromPackageJson }); } } }); return result; function isImportable(program, moduleFile, isFromPackageJson) { var _a; return !moduleFile || ts.isImportableFile(program, importingFile, moduleFile, preferences, /*packageJsonFilter*/ undefined, getModuleSpecifierResolutionHost(isFromPackageJson), (_a = host.getModuleSpecifierCache) === null || _a === void 0 ? void 0 : _a.call(host)); } } function getImportFixes(exportInfos, useNamespaceInfo, /** undefined only for missing JSX namespace */ isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, importMap, fromCacheOnly) { if (importMap === void 0) { importMap = createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()); } var checker = program.getTypeChecker(); var existingImports = ts.flatMap(exportInfos, importMap.getImportsForExportInfo); var useNamespace = useNamespaceInfo && tryUseExistingNamespaceImport(existingImports, useNamespaceInfo.symbolName, useNamespaceInfo.position, checker); var addToExisting = tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, program.getCompilerOptions()); if (addToExisting) { // Don't bother providing an action to add a new import if we can add to an existing one. return { computedWithoutCacheCount: 0, fixes: __spreadArray(__spreadArray([], (useNamespace ? [useNamespace] : ts.emptyArray), true), [addToExisting], false), }; } var _a = getFixesForAddImport(exportInfos, existingImports, program, sourceFile, useNamespaceInfo === null || useNamespaceInfo === void 0 ? void 0 : useNamespaceInfo.position, isValidTypeOnlyUseSite, useRequire, host, preferences, fromCacheOnly), fixes = _a.fixes, _b = _a.computedWithoutCacheCount, computedWithoutCacheCount = _b === void 0 ? 0 : _b; return { computedWithoutCacheCount: computedWithoutCacheCount, fixes: __spreadArray(__spreadArray([], (useNamespace ? [useNamespace] : ts.emptyArray), true), fixes, true), }; } 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 _b; var declaration = _a.declaration; var namespacePrefix = getNamespaceLikeImportText(declaration); var moduleSpecifier = (_b = ts.tryGetModuleSpecifierFromDeclaration(declaration)) === null || _b === void 0 ? void 0 : _b.text; if (namespacePrefix && moduleSpecifier) { var moduleSymbol = getTargetModuleFromNamespaceLikeImport(declaration, checker); if (moduleSymbol && moduleSymbol.exports.has(ts.escapeLeadingUnderscores(symbolName))) { return { kind: 0 /* ImportFixKind.UseNamespace */, namespacePrefix: namespacePrefix, position: position, moduleSpecifier: moduleSpecifier }; } } }); } function getTargetModuleFromNamespaceLikeImport(declaration, checker) { var _a; switch (declaration.kind) { case 254 /* SyntaxKind.VariableDeclaration */: return checker.resolveExternalModuleName(declaration.initializer.arguments[0]); case 265 /* SyntaxKind.ImportEqualsDeclaration */: return checker.getAliasedSymbol(declaration.symbol); case 266 /* SyntaxKind.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 254 /* SyntaxKind.VariableDeclaration */: return (_a = ts.tryCast(declaration.name, ts.isIdentifier)) === null || _a === void 0 ? void 0 : _a.text; case 265 /* SyntaxKind.ImportEqualsDeclaration */: return declaration.name.text; case 266 /* SyntaxKind.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 getAddAsTypeOnly(isValidTypeOnlyUseSite, isForNewImportDeclaration, symbol, targetFlags, checker, compilerOptions) { if (!isValidTypeOnlyUseSite) { // Can't use a type-only import if the usage is an emitting position return 4 /* AddAsTypeOnly.NotAllowed */; } if (isForNewImportDeclaration && compilerOptions.importsNotUsedAsValues === 2 /* ImportsNotUsedAsValues.Error */) { // Not writing a (top-level) type-only import here would create an error because the runtime dependency is unnecessary return 2 /* AddAsTypeOnly.Required */; } if (compilerOptions.isolatedModules && compilerOptions.preserveValueImports && (!(targetFlags & 111551 /* SymbolFlags.Value */) || !!checker.getTypeOnlyAliasDeclaration(symbol))) { // A type-only import is required for this symbol if under these settings if the symbol will // be erased, which will happen if the target symbol is purely a type or if it was exported/imported // as type-only already somewhere between this import and the target. return 2 /* AddAsTypeOnly.Required */; } return 1 /* AddAsTypeOnly.Allowed */; } function tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, compilerOptions) { return ts.firstDefined(existingImports, function (_a) { var declaration = _a.declaration, importKind = _a.importKind, symbol = _a.symbol, targetFlags = _a.targetFlags; if (importKind === 3 /* ImportKind.CommonJS */ || importKind === 2 /* ImportKind.Namespace */ || declaration.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { // These kinds of imports are not combinable with anything return undefined; } if (declaration.kind === 254 /* SyntaxKind.VariableDeclaration */) { return (importKind === 0 /* ImportKind.Named */ || importKind === 1 /* ImportKind.Default */) && declaration.name.kind === 201 /* SyntaxKind.ObjectBindingPattern */ ? { kind: 2 /* ImportFixKind.AddToExisting */, importClauseOrBindingPattern: declaration.name, importKind: importKind, moduleSpecifier: declaration.initializer.arguments[0].text, addAsTypeOnly: 4 /* AddAsTypeOnly.NotAllowed */ } : undefined; } var importClause = declaration.importClause; if (!importClause || !ts.isStringLiteralLike(declaration.moduleSpecifier)) return undefined; var name = importClause.name, namedBindings = importClause.namedBindings; // A type-only import may not have both a default and named imports, so the only way a name can // be added to an existing type-only import is adding a named import to existing named bindings. if (importClause.isTypeOnly && !(importKind === 0 /* ImportKind.Named */ && namedBindings)) return undefined; // N.B. we don't have to figure out whether to use the main program checker // or the AutoImportProvider checker because we're adding to an existing import; the existence of // the import guarantees the symbol came from the main program. var addAsTypeOnly = getAddAsTypeOnly(isValidTypeOnlyUseSite, /*isForNewImportDeclaration*/ false, symbol, targetFlags, checker, compilerOptions); if (importKind === 1 /* ImportKind.Default */ && (name || // Cannot add a default import to a declaration that already has one addAsTypeOnly === 2 /* AddAsTypeOnly.Required */ && namedBindings // Cannot add a default import as type-only if the import already has named bindings )) return undefined; if (importKind === 0 /* ImportKind.Named */ && (namedBindings === null || namedBindings === void 0 ? void 0 : namedBindings.kind) === 268 /* SyntaxKind.NamespaceImport */ // Cannot add a named import to a declaration that has a namespace import ) return undefined; return { kind: 2 /* ImportFixKind.AddToExisting */, importClauseOrBindingPattern: importClause, importKind: importKind, moduleSpecifier: declaration.moduleSpecifier.text, addAsTypeOnly: addAsTypeOnly, }; }); } function createExistingImportMap(checker, importingFile, compilerOptions) { var importMap; for (var _i = 0, _a = importingFile.imports; _i < _a.length; _i++) { var moduleSpecifier = _a[_i]; var i = ts.importFromModuleSpecifier(moduleSpecifier); if (ts.isVariableDeclarationInitializedToRequire(i.parent)) { var moduleSymbol = checker.resolveExternalModuleName(moduleSpecifier); if (moduleSymbol) { (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i.parent); } } else if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier); if (moduleSymbol) { (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i); } } } return { getImportsForExportInfo: function (_a) { var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; // Can't use an es6 import for a type in JS. if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) return ts.emptyArray; var matchingDeclarations = importMap === null || importMap === void 0 ? void 0 : importMap.get(ts.getSymbolId(moduleSymbol)); if (!matchingDeclarations) return ts.emptyArray; var importKind = getImportKind(importingFile, exportKind, compilerOptions); return matchingDeclarations.map(function (declaration) { return ({ declaration: declaration, importKind: importKind, symbol: symbol, targetFlags: targetFlags }); }); } }; } function shouldUseRequire(sourceFile, program) { // 1. TypeScript files don't use require variable declarations if (!ts.isSourceFileJS(sourceFile)) { return false; } // 2. If the current source file is unambiguously CJS or ESM, go with that if (sourceFile.commonJsModuleIndicator && !sourceFile.externalModuleIndicator) return true; if (sourceFile.externalModuleIndicator && !sourceFile.commonJsModuleIndicator) return false; // 3. If there's a tsconfig/jsconfig, use its module setting var compilerOptions = program.getCompilerOptions(); if (compilerOptions.configFile) { return ts.getEmitModuleKind(compilerOptions) < ts.ModuleKind.ES2015; } // 4. Match the first other JS file in the program that's unambiguously CJS or ESM for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { var otherFile = _a[_i]; if (otherFile === sourceFile || !ts.isSourceFileJS(otherFile) || program.isSourceFileFromExternalLibrary(otherFile)) continue; if (otherFile.commonJsModuleIndicator && !otherFile.externalModuleIndicator) return true; if (otherFile.externalModuleIndicator && !otherFile.commonJsModuleIndicator) return false; } // 5. Literally nothing to go on return true; } function getNewImportFixes(program, sourceFile, position, isValidTypeOnlyUseSite, useRequire, exportInfo, host, preferences, fromCacheOnly) { var isJs = ts.isSourceFileJS(sourceFile); var compilerOptions = program.getCompilerOptions(); var moduleSpecifierResolutionHost = ts.createModuleSpecifierResolutionHost(program, host); var getChecker = ts.memoizeOne(function (isFromPackageJson) { return isFromPackageJson ? host.getPackageJsonAutoImportProvider().getTypeChecker() : program.getTypeChecker(); }); var rejectNodeModulesRelativePaths = ts.moduleResolutionUsesNodeModules(ts.getEmitModuleResolutionKind(compilerOptions)); var getModuleSpecifiers = fromCacheOnly ? function (moduleSymbol) { return ({ moduleSpecifiers: ts.moduleSpecifiers.tryGetModuleSpecifiersFromCache(moduleSymbol, sourceFile, moduleSpecifierResolutionHost, preferences), computedWithoutCache: false }); } : function (moduleSymbol, checker) { return ts.moduleSpecifiers.getModuleSpecifiersWithCacheInfo(moduleSymbol, checker, compilerOptions, sourceFile, moduleSpecifierResolutionHost, preferences); }; var computedWithoutCacheCount = 0; var fixes = ts.flatMap(exportInfo, function (exportInfo, i) { var checker = getChecker(exportInfo.isFromPackageJson); var _a = getModuleSpecifiers(exportInfo.moduleSymbol, checker), computedWithoutCache = _a.computedWithoutCache, moduleSpecifiers = _a.moduleSpecifiers; var importedSymbolHasValueMeaning = !!(exportInfo.targetFlags & 111551 /* SymbolFlags.Value */); var addAsTypeOnly = getAddAsTypeOnly(isValidTypeOnlyUseSite, /*isForNewImportDeclaration*/ true, exportInfo.symbol, exportInfo.targetFlags, checker, compilerOptions); computedWithoutCacheCount += computedWithoutCache ? 1 : 0; return ts.mapDefined(moduleSpecifiers, function (moduleSpecifier) { return rejectNodeModulesRelativePaths && ts.pathContainsNodeModules(moduleSpecifier) ? undefined : // `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types. !importedSymbolHasValueMeaning && isJs && position !== undefined ? { kind: 1 /* ImportFixKind.JsdocTypeImport */, moduleSpecifier: moduleSpecifier, position: position, exportInfo: exportInfo, isReExport: i > 0 } : { kind: 3 /* ImportFixKind.AddNew */, moduleSpecifier: moduleSpecifier, importKind: getImportKind(sourceFile, exportInfo.exportKind, compilerOptions), useRequire: useRequire, addAsTypeOnly: addAsTypeOnly, exportInfo: exportInfo, isReExport: i > 0, }; }); }); return { computedWithoutCacheCount: computedWithoutCacheCount, fixes: fixes }; } function getFixesForAddImport(exportInfos, existingImports, program, sourceFile, position, isValidTypeOnlyUseSite, useRequire, host, preferences, fromCacheOnly) { var existingDeclaration = ts.firstDefined(existingImports, function (info) { return newImportInfoFromExistingSpecifier(info, isValidTypeOnlyUseSite, useRequire, program.getTypeChecker(), program.getCompilerOptions()); }); return existingDeclaration ? { fixes: [existingDeclaration] } : getNewImportFixes(program, sourceFile, position, isValidTypeOnlyUseSite, useRequire, exportInfos, host, preferences, fromCacheOnly); } function newImportInfoFromExistingSpecifier(_a, isValidTypeOnlyUseSite, useRequire, checker, compilerOptions) { var _b; var declaration = _a.declaration, importKind = _a.importKind, symbol = _a.symbol, targetFlags = _a.targetFlags; var moduleSpecifier = (_b = ts.tryGetModuleSpecifierFromDeclaration(declaration)) === null || _b === void 0 ? void 0 : _b.text; if (moduleSpecifier) { var addAsTypeOnly = useRequire ? 4 /* AddAsTypeOnly.NotAllowed */ : getAddAsTypeOnly(isValidTypeOnlyUseSite, /*isForNewImportDeclaration*/ true, symbol, targetFlags, checker, compilerOptions); return { kind: 3 /* ImportFixKind.AddNew */, moduleSpecifier: moduleSpecifier, importKind: importKind, addAsTypeOnly: addAsTypeOnly, useRequire: useRequire }; } } function getFixesInfo(context, errorCode, pos, useAutoImportProvider) { var symbolToken = ts.getTokenAtPosition(context.sourceFile, pos); var info; if (errorCode === ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) { info = getFixesInfoForUMDImport(context, symbolToken); } else if (!ts.isIdentifier(symbolToken)) { return undefined; } else if (errorCode === ts.Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type.code) { var symbolName_1 = getSymbolName(context.sourceFile, context.program.getTypeChecker(), symbolToken, context.program.getCompilerOptions()); var fix = getTypeOnlyPromotionFix(context.sourceFile, symbolToken, symbolName_1, context.program); return fix && { fixes: [fix], symbolName: symbolName_1, errorIdentifierText: symbolToken.text }; } else { info = getFixesInfoForNonUMDImport(context, symbolToken, useAutoImportProvider); } var packageJsonImportFilter = ts.createPackageJsonImportFilter(context.sourceFile, context.preferences, context.host); return info && __assign(__assign({}, info), { fixes: sortFixes(info.fixes, context.sourceFile, context.program, packageJsonImportFilter, context.host) }); } function sortFixes(fixes, sourceFile, program, packageJsonImportFilter, host) { var _toPath = function (fileName) { return ts.toPath(fileName, host.getCurrentDirectory(), ts.hostGetCanonicalFileName(host)); }; return ts.sort(fixes, function (a, b) { return ts.compareValues(a.kind, b.kind) || compareModuleSpecifiers(a, b, sourceFile, program, packageJsonImportFilter.allowsImportingSpecifier, _toPath); }); } function getBestFix(fixes, sourceFile, program, packageJsonImportFilter, host) { if (!ts.some(fixes)) return; // These will always be placed first if available, and are better than other kinds if (fixes[0].kind === 0 /* ImportFixKind.UseNamespace */ || fixes[0].kind === 2 /* ImportFixKind.AddToExisting */) { return fixes[0]; } return fixes.reduce(function (best, fix) { // Takes true branch of conditional if `fix` is better than `best` return compareModuleSpecifiers(fix, best, sourceFile, program, packageJsonImportFilter.allowsImportingSpecifier, function (fileName) { return ts.toPath(fileName, host.getCurrentDirectory(), ts.hostGetCanonicalFileName(host)); }) === -1 /* Comparison.LessThan */ ? fix : best; }); } /** @returns `Comparison.LessThan` if `a` is better than `b`. */ function compareModuleSpecifiers(a, b, importingFile, program, allowsImportingSpecifier, toPath) { if (a.kind !== 0 /* ImportFixKind.UseNamespace */ && b.kind !== 0 /* ImportFixKind.UseNamespace */) { return ts.compareBooleans(allowsImportingSpecifier(b.moduleSpecifier), allowsImportingSpecifier(a.moduleSpecifier)) || compareNodeCoreModuleSpecifiers(a.moduleSpecifier, b.moduleSpecifier, importingFile, program) || ts.compareBooleans(isFixPossiblyReExportingImportingFile(a, importingFile, program.getCompilerOptions(), toPath), isFixPossiblyReExportingImportingFile(b, importingFile, program.getCompilerOptions(), toPath)) || ts.compareNumberOfDirectorySeparators(a.moduleSpecifier, b.moduleSpecifier); } return 0 /* Comparison.EqualTo */; } // This is a simple heuristic to try to avoid creating an import cycle with a barrel re-export. // E.g., do not `import { Foo } from ".."` when you could `import { Foo } from "../Foo"`. // This can produce false positives or negatives if re-exports cross into sibling directories // (e.g. `export * from "../whatever"`) or are not named "index" (we don't even try to consider // this if we're in a resolution mode where you can't drop trailing "/index" from paths). function isFixPossiblyReExportingImportingFile(fix, importingFile, compilerOptions, toPath) { var _a; if (fix.isReExport && ((_a = fix.exportInfo) === null || _a === void 0 ? void 0 : _a.moduleFileName) && ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs && isIndexFileName(fix.exportInfo.moduleFileName)) { var reExportDir = toPath(ts.getDirectoryPath(fix.exportInfo.moduleFileName)); return ts.startsWith((importingFile.path), reExportDir); } return false; } function isIndexFileName(fileName) { return ts.getBaseFileName(fileName, [".js", ".jsx", ".d.ts", ".ts", ".tsx"], /*ignoreCase*/ true) === "index"; } function compareNodeCoreModuleSpecifiers(a, b, importingFile, program) { if (ts.startsWith(a, "node:") && !ts.startsWith(b, "node:")) return ts.shouldUseUriStyleNodeCoreModules(importingFile, program) ? -1 /* Comparison.LessThan */ : 1 /* Comparison.GreaterThan */; if (ts.startsWith(b, "node:") && !ts.startsWith(a, "node:")) return ts.shouldUseUriStyleNodeCoreModules(importingFile, program) ? 1 /* Comparison.GreaterThan */ : -1 /* Comparison.LessThan */; return 0 /* Comparison.EqualTo */; } function getFixesInfoForUMDImport(_a, token) { var _b; 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 exportInfo = [{ symbol: umdSymbol, moduleSymbol: symbol, moduleFileName: undefined, exportKind: 3 /* ExportKind.UMD */, targetFlags: symbol.flags, isFromPackageJson: false }]; var useRequire = shouldUseRequire(sourceFile, program); var position = ts.isIdentifier(token) ? token.getStart(sourceFile) : undefined; var fixes = getImportFixes(exportInfo, position ? { position: position, symbolName: symbolName } : undefined, /*isValidTypeOnlyUseSite*/ false, useRequire, program, sourceFile, host, preferences).fixes; return { fixes: fixes, symbolName: symbolName, errorIdentifierText: (_b = ts.tryCast(token, ts.isIdentifier)) === null || _b === void 0 ? void 0 : _b.text }; } 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 /* SymbolFlags.Value */, /*excludeGlobals*/ false), ts.isUMDExportSymbol) : undefined; } /** * @param forceImportKeyword Indicates that the user has already typed `import`, so the result must start with `import`. * (In other words, do not allow `const x = require("...")` for JS files.) */ function getImportKind(importingFile, exportKind, compilerOptions, forceImportKeyword) { switch (exportKind) { case 0 /* ExportKind.Named */: return 0 /* ImportKind.Named */; case 1 /* ExportKind.Default */: return 1 /* ImportKind.Default */; case 2 /* ExportKind.ExportEquals */: return getExportEqualsImportKind(importingFile, compilerOptions, !!forceImportKeyword); case 3 /* ExportKind.UMD */: return getUmdImportKind(importingFile, compilerOptions, !!forceImportKeyword); default: return ts.Debug.assertNever(exportKind); } } codefix.getImportKind = getImportKind; function getUmdImportKind(importingFile, compilerOptions, forceImportKeyword) { // Import a synthetic `default` if enabled. if (ts.getAllowSyntheticDefaultImports(compilerOptions)) { return 1 /* ImportKind.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) || forceImportKeyword ? 2 /* ImportKind.Namespace */ : 3 /* ImportKind.CommonJS */; } return 3 /* ImportKind.CommonJS */; case ts.ModuleKind.System: case ts.ModuleKind.ES2015: case ts.ModuleKind.ES2020: case ts.ModuleKind.ES2022: case ts.ModuleKind.ESNext: case ts.ModuleKind.None: // Fall back to the `import * as ns` style import. return 2 /* ImportKind.Namespace */; case ts.ModuleKind.Node16: case ts.ModuleKind.NodeNext: return importingFile.impliedNodeFormat === ts.ModuleKind.ESNext ? 2 /* ImportKind.Namespace */ : 3 /* ImportKind.CommonJS */; default: return ts.Debug.assertNever(moduleKind, "Unexpected moduleKind ".concat(moduleKind)); } } function getFixesInfoForNonUMDImport(_a, symbolToken, useAutoImportProvider) { var sourceFile = _a.sourceFile, program = _a.program, cancellationToken = _a.cancellationToken, host = _a.host, preferences = _a.preferences; var checker = program.getTypeChecker(); var compilerOptions = program.getCompilerOptions(); var symbolName = getSymbolName(sourceFile, checker, symbolToken, compilerOptions); // "default" is a keyword and not a legal identifier for the import, but appears as an identifier. if (symbolName === "default" /* InternalSymbolName.Default */) { return undefined; } var isValidTypeOnlyUseSite = ts.isValidTypeOnlyAliasUseSite(symbolToken); var useRequire = shouldUseRequire(sourceFile, program); var exportInfo = getExportInfos(symbolName, ts.isJSXTagName(symbolToken), ts.getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, program, useAutoImportProvider, host, preferences); var fixes = ts.arrayFrom(ts.flatMapIterator(exportInfo.entries(), function (_a) { var _ = _a[0], exportInfos = _a[1]; return getImportFixes(exportInfos, { symbolName: symbolName, position: symbolToken.getStart(sourceFile) }, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes; })); return { fixes: fixes, symbolName: symbolName, errorIdentifierText: symbolToken.text }; } function getTypeOnlyPromotionFix(sourceFile, symbolToken, symbolName, program) { var checker = program.getTypeChecker(); var symbol = checker.resolveName(symbolName, symbolToken, 111551 /* SymbolFlags.Value */, /*excludeGlobals*/ true); if (!symbol) return undefined; var typeOnlyAliasDeclaration = checker.getTypeOnlyAliasDeclaration(symbol); if (!typeOnlyAliasDeclaration || ts.getSourceFileOfNode(typeOnlyAliasDeclaration) !== sourceFile) return undefined; return { kind: 4 /* ImportFixKind.PromoteTypeOnly */, typeOnlyAliasDeclaration: typeOnlyAliasDeclaration }; } function getSymbolName(sourceFile, checker, symbolToken, compilerOptions) { var parent = symbolToken.parent; if ((ts.isJsxOpeningLikeElement(parent) || ts.isJsxClosingElement(parent)) && parent.tagName === symbolToken && ts.jsxModeNeedsExplicitImport(compilerOptions.jsx)) { var jsxNamespace = checker.getJsxNamespace(sourceFile); if (needsJsxNamespaceFix(jsxNamespace, symbolToken, checker)) { return jsxNamespace; } } return symbolToken.text; } function needsJsxNamespaceFix(jsxNamespace, symbolToken, checker) { if (ts.isIntrinsicJsxName(symbolToken.text)) return true; // If we were triggered by a matching error code on an intrinsic, the error must have been about missing the JSX factory var namespaceSymbol = checker.resolveName(jsxNamespace, symbolToken, 111551 /* SymbolFlags.Value */, /*excludeGlobals*/ true); return !namespaceSymbol || ts.some(namespaceSymbol.declarations, ts.isTypeOnlyImportOrExportDeclaration) && !(namespaceSymbol.flags & 111551 /* SymbolFlags.Value */); } // Returns a map from an exported symbol's ID to a list of every way it's (re-)exported. function getExportInfos(symbolName, isJsxTagName, currentTokenMeaning, cancellationToken, fromFile, program, useAutoImportProvider, host, preferences) { var _a; // 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(); var packageJsonFilter = ts.createPackageJsonImportFilter(fromFile, preferences, host); var moduleSpecifierCache = (_a = host.getModuleSpecifierCache) === null || _a === void 0 ? void 0 : _a.call(host); var getModuleSpecifierResolutionHost = ts.memoizeOne(function (isFromPackageJson) { return ts.createModuleSpecifierResolutionHost(isFromPackageJson ? host.getPackageJsonAutoImportProvider() : program, host); }); function addSymbol(moduleSymbol, toFile, exportedSymbol, exportKind, program, isFromPackageJson) { var moduleSpecifierResolutionHost = getModuleSpecifierResolutionHost(isFromPackageJson); if (toFile && ts.isImportableFile(program, fromFile, toFile, preferences, packageJsonFilter, moduleSpecifierResolutionHost, moduleSpecifierCache) || !toFile && packageJsonFilter.allowsImportingAmbientModule(moduleSymbol, moduleSpecifierResolutionHost)) { var checker = program.getTypeChecker(); originalSymbolToExportInfos.add(ts.getUniqueSymbolId(exportedSymbol, checker).toString(), { symbol: exportedSymbol, moduleSymbol: moduleSymbol, moduleFileName: toFile === null || toFile === void 0 ? void 0 : toFile.fileName, exportKind: exportKind, targetFlags: ts.skipAlias(exportedSymbol, checker).flags, isFromPackageJson: isFromPackageJson }); } } ts.forEachExternalModuleToImportFrom(program, host, useAutoImportProvider, function (moduleSymbol, sourceFile, program, isFromPackageJson) { var checker = program.getTypeChecker(); cancellationToken.throwIfCancellationRequested(); var compilerOptions = program.getCompilerOptions(); var defaultInfo = ts.getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); if (defaultInfo && (defaultInfo.name === symbolName || moduleSymbolToValidIdentifier(moduleSymbol, ts.getEmitScriptTarget(compilerOptions), isJsxTagName) === symbolName) && symbolHasMeaning(defaultInfo.symbolForMeaning, currentTokenMeaning)) { addSymbol(moduleSymbol, sourceFile, defaultInfo.symbol, defaultInfo.exportKind, program, isFromPackageJson); } // check exports with the same name var exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol); if (exportSymbolWithIdenticalName && symbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) { addSymbol(moduleSymbol, sourceFile, exportSymbolWithIdenticalName, 0 /* ExportKind.Named */, program, isFromPackageJson); } }); return originalSymbolToExportInfos; } function getExportEqualsImportKind(importingFile, compilerOptions, forceImportKeyword) { var allowSyntheticDefaults = ts.getAllowSyntheticDefaultImports(compilerOptions); var isJS = ts.isInJSFile(importingFile); // 1. 'import =' will not work in es2015+ TS files, so the decision is between a default // and a namespace import, based on allowSyntheticDefaultImports/esModuleInterop. if (!isJS && ts.getEmitModuleKind(compilerOptions) >= ts.ModuleKind.ES2015) { return allowSyntheticDefaults ? 1 /* ImportKind.Default */ : 2 /* ImportKind.Namespace */; } // 2. 'import =' will not work in JavaScript, so the decision is between a default import, // a namespace import, and const/require. if (isJS) { return ts.isExternalModule(importingFile) || forceImportKeyword ? allowSyntheticDefaults ? 1 /* ImportKind.Default */ : 2 /* ImportKind.Namespace */ : 3 /* ImportKind.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]; // `import foo` parses as an ImportEqualsDeclaration even though it could be an ImportDeclaration if (ts.isImportEqualsDeclaration(statement) && !ts.nodeIsMissing(statement.moduleReference)) { return 3 /* ImportKind.CommonJS */; } } // 4. We have no precedent to go on, so just use a default import if // allowSyntheticDefaultImports/esModuleInterop is enabled. return allowSyntheticDefaults ? 1 /* ImportKind.Default */ : 3 /* ImportKind.CommonJS */; } function codeActionForFix(context, sourceFile, symbolName, fix, includeSymbolNameInDescription, quotePreference, compilerOptions) { var diag; var changes = ts.textChanges.ChangeTracker.with(context, function (tracker) { diag = codeActionForFixWorker(tracker, sourceFile, symbolName, fix, includeSymbolNameInDescription, quotePreference, compilerOptions); }); return codefix.createCodeFixAction(codefix.importFixName, changes, diag, importFixId, ts.Diagnostics.Add_all_missing_imports); } function codeActionForFixWorker(changes, sourceFile, symbolName, fix, includeSymbolNameInDescription, quotePreference, compilerOptions) { switch (fix.kind) { case 0 /* ImportFixKind.UseNamespace */: addNamespaceQualifier(changes, sourceFile, fix); return [ts.Diagnostics.Change_0_to_1, symbolName, "".concat(fix.namespacePrefix, ".").concat(symbolName)]; case 1 /* ImportFixKind.JsdocTypeImport */: addImportType(changes, sourceFile, fix, quotePreference); return [ts.Diagnostics.Change_0_to_1, symbolName, getImportTypePrefix(fix.moduleSpecifier, quotePreference) + symbolName]; case 2 /* ImportFixKind.AddToExisting */: { var importClauseOrBindingPattern = fix.importClauseOrBindingPattern, importKind = fix.importKind, addAsTypeOnly = fix.addAsTypeOnly, moduleSpecifier = fix.moduleSpecifier; doAddExistingFix(changes, sourceFile, importClauseOrBindingPattern, importKind === 1 /* ImportKind.Default */ ? { name: symbolName, addAsTypeOnly: addAsTypeOnly } : undefined, importKind === 0 /* ImportKind.Named */ ? [{ name: symbolName, addAsTypeOnly: addAsTypeOnly }] : ts.emptyArray, compilerOptions); var moduleSpecifierWithoutQuotes = ts.stripQuotes(moduleSpecifier); return includeSymbolNameInDescription ? [ts.Diagnostics.Import_0_from_1, symbolName, moduleSpecifierWithoutQuotes] : [ts.Diagnostics.Update_import_from_0, moduleSpecifierWithoutQuotes]; } case 3 /* ImportFixKind.AddNew */: { var importKind = fix.importKind, moduleSpecifier = fix.moduleSpecifier, addAsTypeOnly = fix.addAsTypeOnly, useRequire = fix.useRequire; var getDeclarations = useRequire ? getNewRequires : getNewImports; var defaultImport = importKind === 1 /* ImportKind.Default */ ? { name: symbolName, addAsTypeOnly: addAsTypeOnly } : undefined; var namedImports = importKind === 0 /* ImportKind.Named */ ? [{ name: symbolName, addAsTypeOnly: addAsTypeOnly }] : undefined; var namespaceLikeImport = importKind === 2 /* ImportKind.Namespace */ || importKind === 3 /* ImportKind.CommonJS */ ? { importKind: importKind, name: symbolName, addAsTypeOnly: addAsTypeOnly } : undefined; ts.insertImports(changes, sourceFile, getDeclarations(moduleSpecifier, quotePreference, defaultImport, namedImports, namespaceLikeImport), /*blankLineBetween*/ true); return includeSymbolNameInDescription ? [ts.Diagnostics.Import_0_from_1, symbolName, moduleSpecifier] : [ts.Diagnostics.Add_import_from_0, moduleSpecifier]; } case 4 /* ImportFixKind.PromoteTypeOnly */: { var typeOnlyAliasDeclaration = fix.typeOnlyAliasDeclaration; var promotedDeclaration = promoteFromTypeOnly(changes, typeOnlyAliasDeclaration, compilerOptions, sourceFile); return promotedDeclaration.kind === 270 /* SyntaxKind.ImportSpecifier */ ? [ts.Diagnostics.Remove_type_from_import_of_0_from_1, symbolName, getModuleSpecifierText(promotedDeclaration.parent.parent)] : [ts.Diagnostics.Remove_type_from_import_declaration_from_0, getModuleSpecifierText(promotedDeclaration)]; } default: return ts.Debug.assertNever(fix, "Unexpected fix kind ".concat(fix.kind)); } } function getModuleSpecifierText(promotedDeclaration) { var _a, _b; return promotedDeclaration.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */ ? ((_b = ts.tryCast((_a = ts.tryCast(promotedDeclaration.moduleReference, ts.isExternalModuleReference)) === null || _a === void 0 ? void 0 : _a.expression, ts.isStringLiteralLike)) === null || _b === void 0 ? void 0 : _b.text) || promotedDeclaration.moduleReference.getText() : ts.cast(promotedDeclaration.parent.moduleSpecifier, ts.isStringLiteral).text; } function promoteFromTypeOnly(changes, aliasDeclaration, compilerOptions, sourceFile) { // See comment in `doAddExistingFix` on constant with the same name. var convertExistingToTypeOnly = compilerOptions.preserveValueImports && compilerOptions.isolatedModules; switch (aliasDeclaration.kind) { case 270 /* SyntaxKind.ImportSpecifier */: if (aliasDeclaration.isTypeOnly) { if (aliasDeclaration.parent.elements.length > 1 && ts.OrganizeImports.importSpecifiersAreSorted(aliasDeclaration.parent.elements)) { changes.delete(sourceFile, aliasDeclaration); var newSpecifier = ts.factory.updateImportSpecifier(aliasDeclaration, /*isTypeOnly*/ false, aliasDeclaration.propertyName, aliasDeclaration.name); var insertionIndex = ts.OrganizeImports.getImportSpecifierInsertionIndex(aliasDeclaration.parent.elements, newSpecifier); changes.insertImportSpecifierAtIndex(sourceFile, newSpecifier, aliasDeclaration.parent, insertionIndex); } else { changes.deleteRange(sourceFile, aliasDeclaration.getFirstToken()); } return aliasDeclaration; } else { ts.Debug.assert(aliasDeclaration.parent.parent.isTypeOnly); promoteImportClause(aliasDeclaration.parent.parent); return aliasDeclaration.parent.parent; } case 267 /* SyntaxKind.ImportClause */: promoteImportClause(aliasDeclaration); return aliasDeclaration; case 268 /* SyntaxKind.NamespaceImport */: promoteImportClause(aliasDeclaration.parent); return aliasDeclaration.parent; case 265 /* SyntaxKind.ImportEqualsDeclaration */: changes.deleteRange(sourceFile, aliasDeclaration.getChildAt(1)); return aliasDeclaration; default: ts.Debug.failBadSyntaxKind(aliasDeclaration); } function promoteImportClause(importClause) { changes.delete(sourceFile, ts.getTypeKeywordOfTypeOnlyImport(importClause, sourceFile)); if (convertExistingToTypeOnly) { var namedImports = ts.tryCast(importClause.namedBindings, ts.isNamedImports); if (namedImports && namedImports.elements.length > 1) { if (ts.OrganizeImports.importSpecifiersAreSorted(namedImports.elements) && aliasDeclaration.kind === 270 /* SyntaxKind.ImportSpecifier */ && namedImports.elements.indexOf(aliasDeclaration) !== 0) { // The import specifier being promoted will be the only non-type-only, // import in the NamedImports, so it should be moved to the front. changes.delete(sourceFile, aliasDeclaration); changes.insertImportSpecifierAtIndex(sourceFile, aliasDeclaration, namedImports, 0); } for (var _i = 0, _a = namedImports.elements; _i < _a.length; _i++) { var element = _a[_i]; if (element !== aliasDeclaration && !element.isTypeOnly) { changes.insertModifierBefore(sourceFile, 152 /* SyntaxKind.TypeKeyword */, element); } } } } } } function doAddExistingFix(changes, sourceFile, clause, defaultImport, namedImports, compilerOptions) { var _a; if (clause.kind === 201 /* SyntaxKind.ObjectBindingPattern */) { if (defaultImport) { addElementToBindingPattern(clause, defaultImport.name, "default"); } for (var _i = 0, namedImports_1 = namedImports; _i < namedImports_1.length; _i++) { var specifier = namedImports_1[_i]; addElementToBindingPattern(clause, specifier.name, /*propertyName*/ undefined); } return; } var promoteFromTypeOnly = clause.isTypeOnly && ts.some(__spreadArray([defaultImport], namedImports, true), function (i) { return (i === null || i === void 0 ? void 0 : i.addAsTypeOnly) === 4 /* AddAsTypeOnly.NotAllowed */; }); var existingSpecifiers = clause.namedBindings && ((_a = ts.tryCast(clause.namedBindings, ts.isNamedImports)) === null || _a === void 0 ? void 0 : _a.elements); // If we are promoting from a type-only import and `--isolatedModules` and `--preserveValueImports` // are enabled, we need to make every existing import specifier type-only. It may be possible that // some of them don't strictly need to be marked type-only (if they have a value meaning and are // never used in an emitting position). These are allowed to be imported without being type-only, // but the user has clearly already signified that they don't need them to be present at runtime // by placing them in a type-only import. So, just mark each specifier as type-only. var convertExistingToTypeOnly = promoteFromTypeOnly && compilerOptions.preserveValueImports && compilerOptions.isolatedModules; 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.factory.createIdentifier(defaultImport.name), { suffix: ", " }); } if (namedImports.length) { var newSpecifiers = ts.stableSort(namedImports.map(function (namedImport) { return ts.factory.createImportSpecifier((!clause.isTypeOnly || promoteFromTypeOnly) && needsTypeOnly(namedImport), /*propertyName*/ undefined, ts.factory.createIdentifier(namedImport.name)); }), ts.OrganizeImports.compareImportOrExportSpecifiers); if ((existingSpecifiers === null || existingSpecifiers === void 0 ? void 0 : existingSpecifiers.length) && ts.OrganizeImports.importSpecifiersAreSorted(existingSpecifiers)) { for (var _b = 0, newSpecifiers_1 = newSpecifiers; _b < newSpecifiers_1.length; _b++) { var spec = newSpecifiers_1[_b]; // Organize imports puts type-only import specifiers last, so if we're // adding a non-type-only specifier and converting all the other ones to // type-only, there's no need to ask for the insertion index - it's 0. var insertionIndex = convertExistingToTypeOnly && !spec.isTypeOnly ? 0 : ts.OrganizeImports.getImportSpecifierInsertionIndex(existingSpecifiers, spec); changes.insertImportSpecifierAtIndex(sourceFile, spec, clause.namedBindings, insertionIndex); } } else if (existingSpecifiers === null || existingSpecifiers === void 0 ? void 0 : existingSpecifiers.length) { for (var _c = 0, newSpecifiers_2 = newSpecifiers; _c < newSpecifiers_2.length; _c++) { var spec = newSpecifiers_2[_c]; changes.insertNodeInListAfter(sourceFile, ts.last(existingSpecifiers), spec, existingSpecifiers); } } else { if (newSpecifiers.length) { var namedImports_2 = ts.factory.createNamedImports(newSpecifiers); 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 (promoteFromTypeOnly) { changes.delete(sourceFile, ts.getTypeKeywordOfTypeOnlyImport(clause, sourceFile)); if (convertExistingToTypeOnly && existingSpecifiers) { for (var _d = 0, existingSpecifiers_1 = existingSpecifiers; _d < existingSpecifiers_1.length; _d++) { var specifier = existingSpecifiers_1[_d]; changes.insertModifierBefore(sourceFile, 152 /* SyntaxKind.TypeKeyword */, specifier); } } } function addElementToBindingPattern(bindingPattern, name, propertyName) { var element = ts.factory.createBindingElement(/*dotDotDotToken*/ undefined, propertyName, name); if (bindingPattern.elements.length) { changes.insertNodeInListAfter(sourceFile, ts.last(bindingPattern.elements), element); } else { changes.replaceNode(sourceFile, bindingPattern, ts.factory.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(".concat(quote).concat(moduleSpecifier).concat(quote, ")."); } function needsTypeOnly(_a) { var addAsTypeOnly = _a.addAsTypeOnly; return addAsTypeOnly === 2 /* AddAsTypeOnly.Required */; } function getNewImports(moduleSpecifier, quotePreference, defaultImport, namedImports, namespaceLikeImport) { var quotedModuleSpecifier = ts.makeStringLiteral(moduleSpecifier, quotePreference); var statements; if (defaultImport !== undefined || (namedImports === null || namedImports === void 0 ? void 0 : namedImports.length)) { var topLevelTypeOnly_1 = (!defaultImport || needsTypeOnly(defaultImport)) && ts.every(namedImports, needsTypeOnly); statements = ts.combine(statements, ts.makeImport(defaultImport && ts.factory.createIdentifier(defaultImport.name), namedImports === null || namedImports === void 0 ? void 0 : namedImports.map(function (_a) { var addAsTypeOnly = _a.addAsTypeOnly, name = _a.name; return ts.factory.createImportSpecifier(!topLevelTypeOnly_1 && addAsTypeOnly === 2 /* AddAsTypeOnly.Required */, /*propertyName*/ undefined, ts.factory.createIdentifier(name)); }), moduleSpecifier, quotePreference, topLevelTypeOnly_1)); } if (namespaceLikeImport) { var declaration = namespaceLikeImport.importKind === 3 /* ImportKind.CommonJS */ ? ts.factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, needsTypeOnly(namespaceLikeImport), ts.factory.createIdentifier(namespaceLikeImport.name), ts.factory.createExternalModuleReference(quotedModuleSpecifier)) : ts.factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createImportClause(needsTypeOnly(namespaceLikeImport), /*name*/ undefined, ts.factory.createNamespaceImport(ts.factory.createIdentifier(namespaceLikeImport.name))), quotedModuleSpecifier, /*assertClause*/ undefined); statements = ts.combine(statements, declaration); } return ts.Debug.checkDefined(statements); } function getNewRequires(moduleSpecifier, quotePreference, defaultImport, namedImports, namespaceLikeImport) { var quotedModuleSpecifier = ts.makeStringLiteral(moduleSpecifier, quotePreference); var statements; // const { default: foo, bar, etc } = require('./mod'); if (defaultImport || (namedImports === null || namedImports === void 0 ? void 0 : namedImports.length)) { var bindingElements = (namedImports === null || namedImports === void 0 ? void 0 : namedImports.map(function (_a) { var name = _a.name; return ts.factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name); })) || []; if (defaultImport) { bindingElements.unshift(ts.factory.createBindingElement(/*dotDotDotToken*/ undefined, "default", defaultImport.name)); } var declaration = createConstEqualsRequireDeclaration(ts.factory.createObjectBindingPattern(bindingElements), quotedModuleSpecifier); statements = ts.combine(statements, declaration); } // const foo = require('./mod'); if (namespaceLikeImport) { var declaration = createConstEqualsRequireDeclaration(namespaceLikeImport.name, quotedModuleSpecifier); statements = ts.combine(statements, declaration); } return ts.Debug.checkDefined(statements); } function createConstEqualsRequireDeclaration(name, quotedModuleSpecifier) { return ts.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ ts.factory.createVariableDeclaration(typeof name === "string" ? ts.factory.createIdentifier(name) : name, /*exclamationToken*/ undefined, /*type*/ undefined, ts.factory.createCallExpression(ts.factory.createIdentifier("require"), /*typeArguments*/ undefined, [quotedModuleSpecifier])) ], 2 /* NodeFlags.Const */)); } function symbolHasMeaning(_a, meaning) { var declarations = _a.declarations; return ts.some(declarations, function (decl) { return !!(ts.getMeaningFromDeclaration(decl) & meaning); }); } function moduleSymbolToValidIdentifier(moduleSymbol, target, forceCapitalize) { return moduleSpecifierToValidIdentifier(ts.removeFileExtension(ts.stripQuotes(moduleSymbol.name)), target, forceCapitalize); } codefix.moduleSymbolToValidIdentifier = moduleSymbolToValidIdentifier; function moduleSpecifierToValidIdentifier(moduleSpecifier, target, forceCapitalize) { 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); if (forceCapitalize) { res = res.toUpperCase(); } } 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 || "_" : "_".concat(res); } codefix.moduleSpecifierToValidIdentifier = moduleSpecifierToValidIdentifier; })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var _a; var fixName = "fixOverrideModifier"; var fixAddOverrideId = "fixAddOverrideModifier"; var fixRemoveOverrideId = "fixRemoveOverrideModifier"; var errorCodes = [ ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0.code, ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class.code, ts.Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0.code, ts.Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0.code, ts.Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0.code, ts.Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code, ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class.code, ts.Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code, ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0.code, ]; var errorCodeFixIdMap = (_a = {}, // case #1: _a[ts.Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0.code] = { descriptions: ts.Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: ts.Diagnostics.Add_all_missing_override_modifiers, }, _a[ts.Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code] = { descriptions: ts.Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: ts.Diagnostics.Add_all_missing_override_modifiers }, // case #2: _a[ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class.code] = { descriptions: ts.Diagnostics.Remove_override_modifier, fixId: fixRemoveOverrideId, fixAllDescriptions: ts.Diagnostics.Remove_all_unnecessary_override_modifiers, }, _a[ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class.code] = { descriptions: ts.Diagnostics.Remove_override_modifier, fixId: fixRemoveOverrideId, fixAllDescriptions: ts.Diagnostics.Remove_override_modifier }, // case #3: _a[ts.Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0.code] = { descriptions: ts.Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: ts.Diagnostics.Add_all_missing_override_modifiers, }, _a[ts.Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code] = { descriptions: ts.Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: ts.Diagnostics.Add_all_missing_override_modifiers, }, // case #4: _a[ts.Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0.code] = { descriptions: ts.Diagnostics.Add_override_modifier, fixId: fixAddOverrideId, fixAllDescriptions: ts.Diagnostics.Remove_all_unnecessary_override_modifiers, }, // case #5: _a[ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0.code] = { descriptions: ts.Diagnostics.Remove_override_modifier, fixId: fixRemoveOverrideId, fixAllDescriptions: ts.Diagnostics.Remove_all_unnecessary_override_modifiers, }, _a[ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0.code] = { descriptions: ts.Diagnostics.Remove_override_modifier, fixId: fixRemoveOverrideId, fixAllDescriptions: ts.Diagnostics.Remove_all_unnecessary_override_modifiers, }, _a); codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function getCodeActionsToFixOverrideModifierIssues(context) { var errorCode = context.errorCode, span = context.span; var info = errorCodeFixIdMap[errorCode]; if (!info) return ts.emptyArray; var descriptions = info.descriptions, fixId = info.fixId, fixAllDescriptions = info.fixAllDescriptions; var changes = ts.textChanges.ChangeTracker.with(context, function (changes) { return dispatchChanges(changes, context, errorCode, span.start); }); return [ codefix.createCodeFixActionMaybeFixAll(fixName, changes, descriptions, fixId, fixAllDescriptions) ]; }, fixIds: [fixName, fixAddOverrideId, fixRemoveOverrideId], getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var code = diag.code, start = diag.start; var info = errorCodeFixIdMap[code]; if (!info || info.fixId !== context.fixId) { return; } dispatchChanges(changes, context, code, start); }); } }); function dispatchChanges(changeTracker, context, errorCode, pos) { switch (errorCode) { case ts.Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0.code: case ts.Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code: case ts.Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0.code: case ts.Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0.code: case ts.Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0.code: return doAddOverrideModifierChange(changeTracker, context.sourceFile, pos); case ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0.code: case ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0.code: case ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class.code: case ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class.code: return doRemoveOverrideModifierChange(changeTracker, context.sourceFile, pos); default: ts.Debug.fail("Unexpected error code: " + errorCode); } } function doAddOverrideModifierChange(changeTracker, sourceFile, pos) { var classElement = findContainerClassElementLike(sourceFile, pos); if (ts.isSourceFileJS(sourceFile)) { changeTracker.addJSDocTags(sourceFile, classElement, [ts.factory.createJSDocOverrideTag(ts.factory.createIdentifier("override"))]); return; } var modifiers = classElement.modifiers || ts.emptyArray; var staticModifier = ts.find(modifiers, ts.isStaticModifier); var abstractModifier = ts.find(modifiers, ts.isAbstractModifier); var accessibilityModifier = ts.find(modifiers, function (m) { return ts.isAccessibilityModifier(m.kind); }); var modifierPos = abstractModifier ? abstractModifier.end : staticModifier ? staticModifier.end : accessibilityModifier ? accessibilityModifier.end : classElement.decorators ? ts.skipTrivia(sourceFile.text, classElement.decorators.end) : classElement.getStart(sourceFile); var options = accessibilityModifier || staticModifier || abstractModifier ? { prefix: " " } : { suffix: " " }; changeTracker.insertModifierAt(sourceFile, modifierPos, 159 /* SyntaxKind.OverrideKeyword */, options); } function doRemoveOverrideModifierChange(changeTracker, sourceFile, pos) { var classElement = findContainerClassElementLike(sourceFile, pos); if (ts.isSourceFileJS(sourceFile)) { changeTracker.filterJSDocTags(sourceFile, classElement, ts.not(ts.isJSDocOverrideTag)); return; } var overrideModifier = classElement.modifiers && ts.find(classElement.modifiers, function (modifier) { return modifier.kind === 159 /* SyntaxKind.OverrideKeyword */; }); ts.Debug.assertIsDefined(overrideModifier); changeTracker.deleteModifier(sourceFile, overrideModifier); } function isClassElementLikeHasJSDoc(node) { switch (node.kind) { case 171 /* SyntaxKind.Constructor */: case 167 /* SyntaxKind.PropertyDeclaration */: case 169 /* SyntaxKind.MethodDeclaration */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: return true; case 164 /* SyntaxKind.Parameter */: return ts.isParameterPropertyDeclaration(node, node.parent); default: return false; } } function findContainerClassElementLike(sourceFile, pos) { var token = ts.getTokenAtPosition(sourceFile, pos); var classElement = ts.findAncestor(token, function (node) { if (ts.isClassLike(node)) return "quit"; return isClassElementLikeHasJSDoc(node); }); ts.Debug.assert(classElement && isClassElementLikeHasJSDoc(classElement)); return classElement; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixId = "fixNoPropertyAccessFromIndexSignature"; var errorCodes = [ ts.Diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0.code ]; codefix.registerCodeFix({ errorCodes: errorCodes, fixIds: [fixId], getCodeActions: function (context) { var sourceFile = context.sourceFile, span = context.span, preferences = context.preferences; var property = getPropertyAccessExpression(sourceFile, span.start); var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, property, preferences); }); return [codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Use_element_access_for_0, property.name.text], fixId, ts.Diagnostics.Use_element_access_for_all_undeclared_properties)]; }, getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, getPropertyAccessExpression(diag.file, diag.start), context.preferences); }); } }); function doChange(changes, sourceFile, node, preferences) { var quotePreference = ts.getQuotePreference(sourceFile, preferences); var argumentsExpression = ts.factory.createStringLiteral(node.name.text, quotePreference === 0 /* QuotePreference.Single */); changes.replaceNode(sourceFile, node, ts.isPropertyAccessChain(node) ? ts.factory.createElementAccessChain(node.expression, node.questionDotToken, argumentsExpression) : ts.factory.createElementAccessExpression(node.expression, argumentsExpression)); } function getPropertyAccessExpression(sourceFile, pos) { return ts.cast(ts.getTokenAtPosition(sourceFile, pos).parent, ts.isPropertyAccessExpression); } })(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 getCodeActionsToFixImplicitThis(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); if (!ts.isThis(token)) return undefined; 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.checkDefined(ts.findChildOfKind(fn, 98 /* SyntaxKind.FunctionKeyword */, sourceFile)); var name = fn.name; var body = ts.Debug.checkDefined(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.factory.createToken(85 /* SyntaxKind.ConstKeyword */)); changes.insertText(sourceFile, name.end, " = "); changes.insertText(sourceFile, body.pos, " =>"); return [ts.Diagnostics.Convert_function_declaration_0_to_arrow_function, name.text]; } } } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixId = "fixIncorrectNamedTupleSyntax"; var errorCodes = [ ts.Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type.code, ts.Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type.code ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function getCodeActionsToFixIncorrectNamedTupleSyntax(context) { var sourceFile = context.sourceFile, span = context.span; var namedTupleMember = getNamedTupleMember(sourceFile, span.start); var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, namedTupleMember); }); return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Move_labeled_tuple_element_modifiers_to_labels, fixId, ts.Diagnostics.Move_labeled_tuple_element_modifiers_to_labels)]; }, fixIds: [fixId] }); function getNamedTupleMember(sourceFile, pos) { var token = ts.getTokenAtPosition(sourceFile, pos); return ts.findAncestor(token, function (t) { return t.kind === 197 /* SyntaxKind.NamedTupleMember */; }); } function doChange(changes, sourceFile, namedTupleMember) { if (!namedTupleMember) { return; } var unwrappedType = namedTupleMember.type; var sawOptional = false; var sawRest = false; while (unwrappedType.kind === 185 /* SyntaxKind.OptionalType */ || unwrappedType.kind === 186 /* SyntaxKind.RestType */ || unwrappedType.kind === 191 /* SyntaxKind.ParenthesizedType */) { if (unwrappedType.kind === 185 /* SyntaxKind.OptionalType */) { sawOptional = true; } else if (unwrappedType.kind === 186 /* SyntaxKind.RestType */) { sawRest = true; } unwrappedType = unwrappedType.type; } var updated = ts.factory.updateNamedTupleMember(namedTupleMember, namedTupleMember.dotDotDotToken || (sawRest ? ts.factory.createToken(25 /* SyntaxKind.DotDotDotToken */) : undefined), namedTupleMember.name, namedTupleMember.questionToken || (sawOptional ? ts.factory.createToken(57 /* SyntaxKind.QuestionToken */) : undefined), unwrappedType); if (updated === namedTupleMember) { return; } changes.replaceNode(sourceFile, namedTupleMember, updated); } })(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.Property_0_may_not_exist_on_type_1_Did_you_mean_2.code, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1.code, ts.Diagnostics.Could_not_find_name_0_Did_you_mean_1.code, ts.Diagnostics.Cannot_find_namespace_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._0_has_no_exported_member_named_1_Did_you_mean_2.code, ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1.code, ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1.code, // for JSX class components ts.Diagnostics.No_overload_matches_this_call.code, // for JSX FC ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var sourceFile = context.sourceFile, errorCode = context.errorCode; var info = getInfo(sourceFile, context.span.start, context, errorCode); if (!info) return undefined; var node = info.node, suggestedSymbol = info.suggestedSymbol; var target = ts.getEmitScriptTarget(context.host.getCompilationSettings()); 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, diag.code); var target = ts.getEmitScriptTarget(context.host.getCompilationSettings()); if (info) doChange(changes, context.sourceFile, info.node, info.suggestedSymbol, target); }); }, }); function getInfo(sourceFile, pos, context, errorCode) { // This is the identifier of the misspelled word. eg: // this.speling = 1; // ^^^^^^^ var node = ts.getTokenAtPosition(sourceFile, pos); var parent = node.parent; // Only fix spelling for No_overload_matches_this_call emitted on the React class component if ((errorCode === ts.Diagnostics.No_overload_matches_this_call.code || errorCode === ts.Diagnostics.Type_0_is_not_assignable_to_type_1.code) && !ts.isJsxAttribute(parent)) return undefined; var checker = context.program.getTypeChecker(); var suggestedSymbol; if (ts.isPropertyAccessExpression(parent) && parent.name === node) { ts.Debug.assert(ts.isMemberName(node), "Expected an identifier for spelling (property access)"); var containingType = checker.getTypeAtLocation(parent.expression); if (parent.flags & 32 /* NodeFlags.OptionalChain */) { containingType = checker.getNonNullableType(containingType); } suggestedSymbol = checker.getSuggestedSymbolForNonexistentProperty(node, containingType); } else if (ts.isBinaryExpression(parent) && parent.operatorToken.kind === 101 /* SyntaxKind.InKeyword */ && parent.left === node && ts.isPrivateIdentifier(node)) { var receiverType = checker.getTypeAtLocation(parent.right); suggestedSymbol = checker.getSuggestedSymbolForNonexistentProperty(node, receiverType); } else if (ts.isQualifiedName(parent) && parent.right === node) { var symbol = checker.getSymbolAtLocation(parent.left); if (symbol && symbol.flags & 1536 /* SymbolFlags.Module */) { suggestedSymbol = checker.getSuggestedSymbolForNonexistentModule(parent.right, symbol); } } 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 if (ts.isJsxAttribute(parent) && parent.name === node) { ts.Debug.assertNode(node, ts.isIdentifier, "Expected an identifier for JSX attribute"); var tag = ts.findAncestor(node, ts.isJsxOpeningLikeElement); var props = checker.getContextualTypeForArgumentAtIndex(tag, 0); suggestedSymbol = checker.getSuggestedSymbolForNonexistentJSXAttribute(node, props); } else if (ts.hasSyntacticModifier(parent, 16384 /* ModifierFlags.Override */) && ts.isClassElement(parent) && parent.name === node) { var baseDeclaration = ts.findAncestor(node, ts.isClassLike); var baseTypeNode = baseDeclaration ? ts.getEffectiveBaseTypeNode(baseDeclaration) : undefined; var baseType = baseTypeNode ? checker.getTypeAtLocation(baseTypeNode) : undefined; if (baseType) { suggestedSymbol = checker.getSuggestedSymbolForNonexistentClassMember(ts.getTextOfNode(node), baseType); } } 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 (valDecl && ts.isNamedDeclaration(valDecl) && ts.isPrivateIdentifier(valDecl.name)) { changes.replaceNode(sourceFile, node, ts.factory.createIdentifier(suggestion)); } else { changes.replaceNode(sourceFile, node.parent, ts.factory.createElementAccessExpression(node.parent.expression, ts.factory.createStringLiteral(suggestion))); } } else { changes.replaceNode(sourceFile, node, ts.factory.createIdentifier(suggestion)); } } function convertSemanticMeaningToSymbolFlags(meaning) { var flags = 0; if (meaning & 4 /* SemanticMeaning.Namespace */) { flags |= 1920 /* SymbolFlags.Namespace */; } if (meaning & 2 /* SemanticMeaning.Type */) { flags |= 788968 /* SymbolFlags.Type */; } if (meaning & 1 /* SemanticMeaning.Value */) { flags |= 111551 /* SymbolFlags.Value */; } return flags; } function getResolvedSourceFileFromImportDeclaration(sourceFile, context, importDeclaration) { if (!importDeclaration || !ts.isStringLiteralLike(importDeclaration.moduleSpecifier)) return undefined; var resolvedModule = ts.getResolvedModule(sourceFile, importDeclaration.moduleSpecifier.text, ts.getModeForUsageLocation(sourceFile, importDeclaration.moduleSpecifier)); 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 fixRemoveBracesFromArrowFunctionBody = "fixRemoveBracesFromArrowFunctionBody"; 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, fixRemoveBracesFromArrowFunctionBody, fixIdWrapTheBlockWithParen], getCodeActions: function getCodeActionsToCorrectReturnValue(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) ? getActionForFixRemoveBracesFromArrowFunctionBody(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 fixRemoveBracesFromArrowFunctionBody: 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 createObjectTypeFromLabeledExpression(checker, label, expression) { var member = checker.createSymbol(4 /* SymbolFlags.Property */, label.escapedText); member.type = checker.getTypeAtLocation(expression); var members = ts.createSymbolTable([member]); return checker.createAnonymousType(/*symbol*/ undefined, members, [], [], []); } 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, checker.getTypeAtLocation(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.factory.createObjectLiteralExpression([ts.factory.createPropertyAssignment(firstStatement.label, firstStatement.statement.expression)]); var nodeType = createObjectTypeFromLabeledExpression(checker, firstStatement.label, firstStatement.statement.expression); if (checkFixedAssignableTo(checker, declaration, nodeType, 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.factory.createObjectLiteralExpression([ts.factory.createPropertyAssignment(firstBlockStatement.label, firstBlockStatement.statement.expression)]); var nodeType = createObjectTypeFromLabeledExpression(checker, firstBlockStatement.label, firstBlockStatement.statement.expression); if (checkFixedAssignableTo(checker, declaration, nodeType, expectType, isFunctionType)) { return { declaration: declaration, kind: ProblemKind.MissingReturnStatement, expression: node, statement: firstStatement, commentSource: firstBlockStatement }; } } } return undefined; } function checkFixedAssignableTo(checker, declaration, exprType, type, isFunctionType) { if (isFunctionType) { var sig = checker.getSignatureFromDeclaration(declaration); if (sig) { if (ts.hasSyntacticModifier(declaration, 256 /* ModifierFlags.Async */)) { exprType = checker.createPromiseType(exprType); } var newSig = checker.createSignature(declaration, sig.typeParameters, sig.thisParameter, sig.parameters, exprType, /*typePredicate*/ undefined, sig.minArgumentCount, sig.flags); exprType = checker.createAnonymousType( /*symbol*/ undefined, ts.createSymbolTable(), [newSig], [], []); } else { exprType = checker.getAnyType(); } } return checker.isTypeAssignableTo(exprType, 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 254 /* SyntaxKind.VariableDeclaration */: case 164 /* SyntaxKind.Parameter */: case 203 /* SyntaxKind.BindingElement */: case 167 /* SyntaxKind.PropertyDeclaration */: case 296 /* SyntaxKind.PropertyAssignment */: return declaration.initializer; case 285 /* SyntaxKind.JsxAttribute */: return declaration.initializer && (ts.isJsxExpression(declaration.initializer) ? declaration.initializer.expression : undefined); case 297 /* SyntaxKind.ShorthandPropertyAssignment */: case 166 /* SyntaxKind.PropertySignature */: case 299 /* SyntaxKind.EnumMember */: case 347 /* SyntaxKind.JSDocPropertyTag */: case 340 /* SyntaxKind.JSDocParameterTag */: return undefined; } } function addReturnStatement(changes, sourceFile, expression, statement) { ts.suppressLeadingAndTrailingTrivia(expression); var probablyNeedSemi = ts.probablyUsesSemicolons(sourceFile); changes.replaceNode(sourceFile, statement, ts.factory.createReturnStatement(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.factory.createParenthesizedExpression(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.factory.createParenthesizedExpression(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 getActionForFixRemoveBracesFromArrowFunctionBody(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_braces_from_arrow_function_body, fixRemoveBracesFromArrowFunctionBody, ts.Diagnostics.Remove_braces_from_all_arrow_function_bodies_with_relevant_issues); } 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 fixMissingMember = "fixMissingMember"; var fixMissingProperties = "fixMissingProperties"; var fixMissingAttributes = "fixMissingAttributes"; var fixMissingFunctionDeclaration = "fixMissingFunctionDeclaration"; 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, ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code, ts.Diagnostics.Cannot_find_name_0.code ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var typeChecker = context.program.getTypeChecker(); var info = getInfo(context.sourceFile, context.span.start, context.errorCode, typeChecker, context.program); if (!info) { return undefined; } if (info.kind === 3 /* InfoKind.ObjectLiteral */) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addObjectLiteralProperties(t, context, info); }); return [codefix.createCodeFixAction(fixMissingProperties, changes, ts.Diagnostics.Add_missing_properties, fixMissingProperties, ts.Diagnostics.Add_all_missing_properties)]; } if (info.kind === 4 /* InfoKind.JsxAttributes */) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addJsxAttributes(t, context, info); }); return [codefix.createCodeFixAction(fixMissingAttributes, changes, ts.Diagnostics.Add_missing_attributes, fixMissingAttributes, ts.Diagnostics.Add_all_missing_attributes)]; } if (info.kind === 2 /* InfoKind.Function */) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addFunctionDeclaration(t, context, info); }); return [codefix.createCodeFixAction(fixMissingFunctionDeclaration, changes, [ts.Diagnostics.Add_missing_function_declaration_0, info.token.text], fixMissingFunctionDeclaration, ts.Diagnostics.Add_all_missing_function_declarations)]; } if (info.kind === 1 /* InfoKind.Enum */) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addEnumMemberDeclaration(t, context.program.getTypeChecker(), info); }); return [codefix.createCodeFixAction(fixMissingMember, changes, [ts.Diagnostics.Add_missing_enum_member_0, info.token.text], fixMissingMember, ts.Diagnostics.Add_all_missing_members)]; } return ts.concatenate(getActionsForMissingMethodDeclaration(context, info), getActionsForMissingMemberDeclaration(context, info)); }, fixIds: [fixMissingMember, fixMissingFunctionDeclaration, fixMissingProperties, fixMissingAttributes], getAllCodeActions: function (context) { var program = context.program, fixId = context.fixId; var checker = program.getTypeChecker(); var seen = new ts.Map(); var typeDeclToMembers = new ts.Map(); return codefix.createCombinedCodeActions(ts.textChanges.ChangeTracker.with(context, function (changes) { codefix.eachDiagnostic(context, errorCodes, function (diag) { var info = getInfo(diag.file, diag.start, diag.code, checker, context.program); if (!info || !ts.addToSeen(seen, ts.getNodeId(info.parentDeclaration) + "#" + info.token.text)) { return; } if (fixId === fixMissingFunctionDeclaration && info.kind === 2 /* InfoKind.Function */) { addFunctionDeclaration(changes, context, info); } else if (fixId === fixMissingProperties && info.kind === 3 /* InfoKind.ObjectLiteral */) { addObjectLiteralProperties(changes, context, info); } else if (fixId === fixMissingAttributes && info.kind === 4 /* InfoKind.JsxAttributes */) { addJsxAttributes(changes, context, info); } else { if (info.kind === 1 /* InfoKind.Enum */) { addEnumMemberDeclaration(changes, checker, info); } if (info.kind === 0 /* InfoKind.TypeLikeDeclaration */) { var parentDeclaration = info.parentDeclaration, token_1 = info.token; var infos = ts.getOrUpdate(typeDeclToMembers, parentDeclaration, function () { return []; }); if (!infos.some(function (i) { return i.token.text === token_1.text; })) { infos.push(info); } } } }); typeDeclToMembers.forEach(function (infos, declaration) { var supers = ts.isTypeLiteralNode(declaration) ? undefined : codefix.getAllSupers(declaration, checker); var _loop_15 = function (info) { // If some superclass added this property, don't add it again. if (supers === null || supers === void 0 ? void 0 : 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, modifierFlags = info.modifierFlags, token = info.token, call = info.call, isJSFile = info.isJSFile; // Always prefer to add a method declaration if possible. if (call && !ts.isPrivateIdentifier(token)) { addMethodDeclaration(context, changes, call, token, modifierFlags & 32 /* ModifierFlags.Static */, parentDeclaration, declSourceFile); } else { if (isJSFile && !ts.isInterfaceDeclaration(parentDeclaration) && !ts.isTypeLiteralNode(parentDeclaration)) { addMissingMemberInJs(changes, declSourceFile, parentDeclaration, token, !!(modifierFlags & 32 /* ModifierFlags.Static */)); } else { var typeNode = getTypeNode(checker, parentDeclaration, token); addPropertyDeclaration(changes, declSourceFile, parentDeclaration, token.text, typeNode, modifierFlags & 32 /* ModifierFlags.Static */); } } }; for (var _i = 0, infos_1 = infos; _i < infos_1.length; _i++) { var info = infos_1[_i]; _loop_15(info); } }); })); }, }); var InfoKind; (function (InfoKind) { InfoKind[InfoKind["TypeLikeDeclaration"] = 0] = "TypeLikeDeclaration"; InfoKind[InfoKind["Enum"] = 1] = "Enum"; InfoKind[InfoKind["Function"] = 2] = "Function"; InfoKind[InfoKind["ObjectLiteral"] = 3] = "ObjectLiteral"; InfoKind[InfoKind["JsxAttributes"] = 4] = "JsxAttributes"; })(InfoKind || (InfoKind = {})); function getInfo(sourceFile, tokenPos, errorCode, checker, program) { // The identifier of the missing property. eg: // this.missing = 1; // ^^^^^^^ var token = ts.getTokenAtPosition(sourceFile, tokenPos); var parent = token.parent; if (errorCode === ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1.code) { if (!(token.kind === 18 /* SyntaxKind.OpenBraceToken */ && ts.isObjectLiteralExpression(parent) && ts.isCallExpression(parent.parent))) return undefined; var argIndex = ts.findIndex(parent.parent.arguments, function (arg) { return arg === parent; }); if (argIndex < 0) return undefined; var signature = ts.singleOrUndefined(checker.getSignaturesOfType(checker.getTypeAtLocation(parent.parent.expression), 0 /* SignatureKind.Call */)); if (!(signature && signature.declaration && signature.parameters[argIndex])) return undefined; var param = signature.parameters[argIndex].valueDeclaration; if (!(param && ts.isParameter(param) && ts.isIdentifier(param.name))) return undefined; var properties = ts.arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent), checker.getParameterType(signature, argIndex), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); if (!ts.length(properties)) return undefined; return { kind: 3 /* InfoKind.ObjectLiteral */, token: param.name, properties: properties, parentDeclaration: parent }; } if (!ts.isMemberName(token)) return undefined; if (ts.isIdentifier(token) && ts.hasInitializer(parent) && parent.initializer && ts.isObjectLiteralExpression(parent.initializer)) { var properties = ts.arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent.initializer), checker.getTypeAtLocation(token), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); if (!ts.length(properties)) return undefined; return { kind: 3 /* InfoKind.ObjectLiteral */, token: token, properties: properties, parentDeclaration: parent.initializer }; } if (ts.isIdentifier(token) && ts.isJsxOpeningLikeElement(token.parent)) { var target = ts.getEmitScriptTarget(program.getCompilerOptions()); var attributes = getUnmatchedAttributes(checker, target, token.parent); if (!ts.length(attributes)) return undefined; return { kind: 4 /* InfoKind.JsxAttributes */, token: token, attributes: attributes, parentDeclaration: token.parent }; } if (ts.isIdentifier(token) && ts.isCallExpression(parent)) { return { kind: 2 /* InfoKind.Function */, token: token, call: parent, sourceFile: sourceFile, modifierFlags: 0 /* ModifierFlags.None */, parentDeclaration: sourceFile }; } if (!ts.isPropertyAccessExpression(parent)) return undefined; var leftExpressionType = ts.skipConstraint(checker.getTypeAtLocation(parent.expression)); var symbol = leftExpressionType.symbol; if (!symbol || !symbol.declarations) return undefined; if (ts.isIdentifier(token) && ts.isCallExpression(parent.parent)) { var moduleDeclaration = ts.find(symbol.declarations, ts.isModuleDeclaration); var moduleDeclarationSourceFile = moduleDeclaration === null || moduleDeclaration === void 0 ? void 0 : moduleDeclaration.getSourceFile(); if (moduleDeclaration && moduleDeclarationSourceFile && !isSourceFileFromLibrary(program, moduleDeclarationSourceFile)) { return { kind: 2 /* InfoKind.Function */, token: token, call: parent.parent, sourceFile: sourceFile, modifierFlags: 1 /* ModifierFlags.Export */, parentDeclaration: moduleDeclaration }; } var moduleSourceFile = ts.find(symbol.declarations, ts.isSourceFile); if (sourceFile.commonJsModuleIndicator) return undefined; if (moduleSourceFile && !isSourceFileFromLibrary(program, moduleSourceFile)) { return { kind: 2 /* InfoKind.Function */, token: token, call: parent.parent, sourceFile: moduleSourceFile, modifierFlags: 1 /* ModifierFlags.Export */, parentDeclaration: moduleSourceFile }; } } 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 declaration = classDeclaration || ts.find(symbol.declarations, function (d) { return ts.isInterfaceDeclaration(d) || ts.isTypeLiteralNode(d); }); if (declaration && !isSourceFileFromLibrary(program, declaration.getSourceFile())) { var makeStatic = !ts.isTypeLiteralNode(declaration) && (leftExpressionType.target || leftExpressionType) !== checker.getDeclaredTypeOfSymbol(symbol); if (makeStatic && (ts.isPrivateIdentifier(token) || ts.isInterfaceDeclaration(declaration))) return undefined; var declSourceFile = declaration.getSourceFile(); var modifierFlags = ts.isTypeLiteralNode(declaration) ? 0 /* ModifierFlags.None */ : (makeStatic ? 32 /* ModifierFlags.Static */ : 0 /* ModifierFlags.None */) | (ts.startsWithUnderscore(token.text) ? 8 /* ModifierFlags.Private */ : 0 /* ModifierFlags.None */); var isJSFile = ts.isSourceFileJS(declSourceFile); var call = ts.tryCast(parent.parent, ts.isCallExpression); return { kind: 0 /* InfoKind.TypeLikeDeclaration */, token: token, call: call, modifierFlags: modifierFlags, parentDeclaration: declaration, declSourceFile: declSourceFile, isJSFile: isJSFile }; } var enumDeclaration = ts.find(symbol.declarations, ts.isEnumDeclaration); if (enumDeclaration && !ts.isPrivateIdentifier(token) && !isSourceFileFromLibrary(program, enumDeclaration.getSourceFile())) { return { kind: 1 /* InfoKind.Enum */, token: token, parentDeclaration: enumDeclaration }; } return undefined; } function isSourceFileFromLibrary(program, node) { return program.isSourceFileFromExternalLibrary(node) || program.isSourceFileDefaultLibrary(node); } function getActionsForMissingMemberDeclaration(context, info) { return info.isJSFile ? ts.singleElementArray(createActionForAddMissingMemberInJavascriptFile(context, info)) : createActionsForAddMissingMemberInTypeScriptFile(context, info); } function createActionForAddMissingMemberInJavascriptFile(context, _a) { var parentDeclaration = _a.parentDeclaration, declSourceFile = _a.declSourceFile, modifierFlags = _a.modifierFlags, token = _a.token; if (ts.isInterfaceDeclaration(parentDeclaration) || ts.isTypeLiteralNode(parentDeclaration)) { return undefined; } var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addMissingMemberInJs(t, declSourceFile, parentDeclaration, token, !!(modifierFlags & 32 /* ModifierFlags.Static */)); }); if (changes.length === 0) { return undefined; } var diagnostic = modifierFlags & 32 /* ModifierFlags.Static */ ? 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(fixMissingMember, changes, [diagnostic, token.text], fixMissingMember, ts.Diagnostics.Add_all_missing_members); } function addMissingMemberInJs(changeTracker, sourceFile, classDeclaration, token, makeStatic) { var tokenName = token.text; if (makeStatic) { if (classDeclaration.kind === 226 /* SyntaxKind.ClassExpression */) { return; } var className = classDeclaration.name.getText(); var staticInitialization = initializePropertyToUndefined(ts.factory.createIdentifier(className), tokenName); changeTracker.insertNodeAfter(sourceFile, classDeclaration, staticInitialization); } else if (ts.isPrivateIdentifier(token)) { var property = ts.factory.createPropertyDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, tokenName, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined); var lastProp = getNodeToInsertPropertyAfter(classDeclaration); if (lastProp) { changeTracker.insertNodeAfter(sourceFile, lastProp, property); } else { changeTracker.insertMemberAtStart(sourceFile, classDeclaration, property); } } else { var classConstructor = ts.getFirstConstructorWithBody(classDeclaration); if (!classConstructor) { return; } var propertyInitialization = initializePropertyToUndefined(ts.factory.createThis(), tokenName); changeTracker.insertNodeAtConstructorEnd(sourceFile, classConstructor, propertyInitialization); } } function initializePropertyToUndefined(obj, propertyName) { return ts.factory.createExpressionStatement(ts.factory.createAssignment(ts.factory.createPropertyAccessExpression(obj, propertyName), createUndefined())); } function createActionsForAddMissingMemberInTypeScriptFile(context, _a) { var parentDeclaration = _a.parentDeclaration, declSourceFile = _a.declSourceFile, modifierFlags = _a.modifierFlags, token = _a.token; var memberName = token.text; var isStatic = modifierFlags & 32 /* ModifierFlags.Static */; var typeNode = getTypeNode(context.program.getTypeChecker(), parentDeclaration, token); var addPropertyDeclarationChanges = function (modifierFlags) { return ts.textChanges.ChangeTracker.with(context, function (t) { return addPropertyDeclaration(t, declSourceFile, parentDeclaration, memberName, typeNode, modifierFlags); }); }; var actions = [codefix.createCodeFixAction(fixMissingMember, addPropertyDeclarationChanges(modifierFlags & 32 /* ModifierFlags.Static */), [isStatic ? ts.Diagnostics.Declare_static_property_0 : ts.Diagnostics.Declare_property_0, memberName], fixMissingMember, ts.Diagnostics.Add_all_missing_members)]; if (isStatic || ts.isPrivateIdentifier(token)) { return actions; } if (modifierFlags & 8 /* ModifierFlags.Private */) { actions.unshift(codefix.createCodeFixActionWithoutFixAll(fixMissingMember, addPropertyDeclarationChanges(8 /* ModifierFlags.Private */), [ts.Diagnostics.Declare_private_property_0, memberName])); } actions.push(createAddIndexSignatureAction(context, declSourceFile, parentDeclaration, token.text, typeNode)); return actions; } function getTypeNode(checker, node, token) { var typeNode; if (token.parent.parent.kind === 221 /* SyntaxKind.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, node, 1 /* NodeBuilderFlags.NoTruncation */); } else { var contextualType = checker.getContextualType(token.parent); typeNode = contextualType ? checker.typeToTypeNode(contextualType, /*enclosingDeclaration*/ undefined, 1 /* NodeBuilderFlags.NoTruncation */) : undefined; } return typeNode || ts.factory.createKeywordTypeNode(130 /* SyntaxKind.AnyKeyword */); } function addPropertyDeclaration(changeTracker, sourceFile, node, tokenName, typeNode, modifierFlags) { var modifiers = modifierFlags ? ts.factory.createNodeArray(ts.factory.createModifiersFromModifierFlags(modifierFlags)) : undefined; var property = ts.isClassLike(node) ? ts.factory.createPropertyDeclaration(/*decorators*/ undefined, modifiers, tokenName, /*questionToken*/ undefined, typeNode, /*initializer*/ undefined) : ts.factory.createPropertySignature(/*modifiers*/ undefined, tokenName, /*questionToken*/ undefined, typeNode); var lastProp = getNodeToInsertPropertyAfter(node); if (lastProp) { changeTracker.insertNodeAfter(sourceFile, lastProp, property); } else { changeTracker.insertMemberAtStart(sourceFile, node, property); } } // Gets the last of the first run of PropertyDeclarations, or undefined if the class does not start with a PropertyDeclaration. function getNodeToInsertPropertyAfter(node) { var res; for (var _i = 0, _a = node.members; _i < _a.length; _i++) { var member = _a[_i]; if (!ts.isPropertyDeclaration(member)) break; res = member; } return res; } function createAddIndexSignatureAction(context, sourceFile, node, tokenName, typeNode) { // Index signatures cannot have the static modifier. var stringTypeNode = ts.factory.createKeywordTypeNode(150 /* SyntaxKind.StringKeyword */); var indexingParameter = ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "x", /*questionToken*/ undefined, stringTypeNode, /*initializer*/ undefined); var indexSignature = ts.factory.createIndexSignature( /*decorators*/ undefined, /*modifiers*/ undefined, [indexingParameter], typeNode); var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.insertMemberAtStart(sourceFile, node, indexSignature); }); // No fixId here because code-fix-all currently only works on adding individual named properties. return codefix.createCodeFixActionWithoutFixAll(fixMissingMember, changes, [ts.Diagnostics.Add_index_signature_for_property_0, tokenName]); } function getActionsForMissingMethodDeclaration(context, info) { var parentDeclaration = info.parentDeclaration, declSourceFile = info.declSourceFile, modifierFlags = info.modifierFlags, token = info.token, call = info.call; if (call === undefined) { return undefined; } // Private methods are not implemented yet. if (ts.isPrivateIdentifier(token)) { return undefined; } var methodName = token.text; var addMethodDeclarationChanges = function (modifierFlags) { return ts.textChanges.ChangeTracker.with(context, function (t) { return addMethodDeclaration(context, t, call, token, modifierFlags, parentDeclaration, declSourceFile); }); }; var actions = [codefix.createCodeFixAction(fixMissingMember, addMethodDeclarationChanges(modifierFlags & 32 /* ModifierFlags.Static */), [modifierFlags & 32 /* ModifierFlags.Static */ ? ts.Diagnostics.Declare_static_method_0 : ts.Diagnostics.Declare_method_0, methodName], fixMissingMember, ts.Diagnostics.Add_all_missing_members)]; if (modifierFlags & 8 /* ModifierFlags.Private */) { actions.unshift(codefix.createCodeFixActionWithoutFixAll(fixMissingMember, addMethodDeclarationChanges(8 /* ModifierFlags.Private */), [ts.Diagnostics.Declare_private_method_0, methodName])); } return actions; } function addMethodDeclaration(context, changes, callExpression, name, modifierFlags, parentDeclaration, sourceFile) { var importAdder = codefix.createImportAdder(sourceFile, context.program, context.preferences, context.host); var kind = ts.isClassLike(parentDeclaration) ? 169 /* SyntaxKind.MethodDeclaration */ : 168 /* SyntaxKind.MethodSignature */; var signatureDeclaration = codefix.createSignatureDeclarationFromCallExpression(kind, context, importAdder, callExpression, name, modifierFlags, parentDeclaration); var containingMethodDeclaration = tryGetContainingMethodDeclaration(parentDeclaration, callExpression); if (containingMethodDeclaration) { changes.insertNodeAfter(sourceFile, containingMethodDeclaration, signatureDeclaration); } else { changes.insertMemberAtStart(sourceFile, parentDeclaration, signatureDeclaration); } importAdder.writeFixes(changes); } function addEnumMemberDeclaration(changes, checker, _a) { var token = _a.token, parentDeclaration = _a.parentDeclaration; /** * 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(parentDeclaration.members, function (member) { var type = checker.getTypeAtLocation(member); return !!(type && type.flags & 402653316 /* TypeFlags.StringLike */); }); var enumMember = ts.factory.createEnumMember(token, hasStringInitializer ? ts.factory.createStringLiteral(token.text) : undefined); changes.replaceNode(parentDeclaration.getSourceFile(), parentDeclaration, ts.factory.updateEnumDeclaration(parentDeclaration, parentDeclaration.decorators, parentDeclaration.modifiers, parentDeclaration.name, ts.concatenate(parentDeclaration.members, ts.singleElementArray(enumMember))), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude }); } function addFunctionDeclaration(changes, context, info) { var importAdder = codefix.createImportAdder(context.sourceFile, context.program, context.preferences, context.host); var functionDeclaration = codefix.createSignatureDeclarationFromCallExpression(256 /* SyntaxKind.FunctionDeclaration */, context, importAdder, info.call, ts.idText(info.token), info.modifierFlags, info.parentDeclaration); changes.insertNodeAtEndOfScope(info.sourceFile, info.parentDeclaration, functionDeclaration); } function addJsxAttributes(changes, context, info) { var importAdder = codefix.createImportAdder(context.sourceFile, context.program, context.preferences, context.host); var quotePreference = ts.getQuotePreference(context.sourceFile, context.preferences); var checker = context.program.getTypeChecker(); var jsxAttributesNode = info.parentDeclaration.attributes; var hasSpreadAttribute = ts.some(jsxAttributesNode.properties, ts.isJsxSpreadAttribute); var attrs = ts.map(info.attributes, function (attr) { var value = tryGetValueFromType(context, checker, importAdder, quotePreference, checker.getTypeOfSymbol(attr)); var name = ts.factory.createIdentifier(attr.name); var jsxAttribute = ts.factory.createJsxAttribute(name, ts.factory.createJsxExpression(/*dotDotDotToken*/ undefined, value)); // formattingScanner requires the Identifier to have a context for scanning attributes with "-" (data-foo). ts.setParent(name, jsxAttribute); return jsxAttribute; }); var jsxAttributes = ts.factory.createJsxAttributes(hasSpreadAttribute ? __spreadArray(__spreadArray([], attrs, true), jsxAttributesNode.properties, true) : __spreadArray(__spreadArray([], jsxAttributesNode.properties, true), attrs, true)); var options = { prefix: jsxAttributesNode.pos === jsxAttributesNode.end ? " " : undefined }; changes.replaceNode(context.sourceFile, jsxAttributesNode, jsxAttributes, options); } function addObjectLiteralProperties(changes, context, info) { var importAdder = codefix.createImportAdder(context.sourceFile, context.program, context.preferences, context.host); var quotePreference = ts.getQuotePreference(context.sourceFile, context.preferences); var target = ts.getEmitScriptTarget(context.program.getCompilerOptions()); var checker = context.program.getTypeChecker(); var props = ts.map(info.properties, function (prop) { var initializer = tryGetValueFromType(context, checker, importAdder, quotePreference, checker.getTypeOfSymbol(prop)); return ts.factory.createPropertyAssignment(ts.createPropertyNameNodeForIdentifierOrLiteral(prop.name, target, quotePreference === 0 /* QuotePreference.Single */), initializer); }); var options = { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude, indentation: info.indentation }; changes.replaceNode(context.sourceFile, info.parentDeclaration, ts.factory.createObjectLiteralExpression(__spreadArray(__spreadArray([], info.parentDeclaration.properties, true), props, true), /*multiLine*/ true), options); } function tryGetValueFromType(context, checker, importAdder, quotePreference, type) { if (type.flags & 3 /* TypeFlags.AnyOrUnknown */) { return createUndefined(); } if (type.flags & (4 /* TypeFlags.String */ | 134217728 /* TypeFlags.TemplateLiteral */)) { return ts.factory.createStringLiteral("", /* isSingleQuote */ quotePreference === 0 /* QuotePreference.Single */); } if (type.flags & 8 /* TypeFlags.Number */) { return ts.factory.createNumericLiteral(0); } if (type.flags & 64 /* TypeFlags.BigInt */) { return ts.factory.createBigIntLiteral("0n"); } if (type.flags & 16 /* TypeFlags.Boolean */) { return ts.factory.createFalse(); } if (type.flags & 1056 /* TypeFlags.EnumLike */) { var enumMember = type.symbol.exports ? ts.firstOrUndefined(ts.arrayFrom(type.symbol.exports.values())) : type.symbol; var name = checker.symbolToExpression(type.symbol.parent ? type.symbol.parent : type.symbol, 111551 /* SymbolFlags.Value */, /*enclosingDeclaration*/ undefined, /*flags*/ undefined); return enumMember === undefined || name === undefined ? ts.factory.createNumericLiteral(0) : ts.factory.createPropertyAccessExpression(name, checker.symbolToString(enumMember)); } if (type.flags & 256 /* TypeFlags.NumberLiteral */) { return ts.factory.createNumericLiteral(type.value); } if (type.flags & 2048 /* TypeFlags.BigIntLiteral */) { return ts.factory.createBigIntLiteral(type.value); } if (type.flags & 128 /* TypeFlags.StringLiteral */) { return ts.factory.createStringLiteral(type.value, /* isSingleQuote */ quotePreference === 0 /* QuotePreference.Single */); } if (type.flags & 512 /* TypeFlags.BooleanLiteral */) { return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? ts.factory.createFalse() : ts.factory.createTrue(); } if (type.flags & 65536 /* TypeFlags.Null */) { return ts.factory.createNull(); } if (type.flags & 1048576 /* TypeFlags.Union */) { var expression = ts.firstDefined(type.types, function (t) { return tryGetValueFromType(context, checker, importAdder, quotePreference, t); }); return expression !== null && expression !== void 0 ? expression : createUndefined(); } if (checker.isArrayLikeType(type)) { return ts.factory.createArrayLiteralExpression(); } if (isObjectLiteralType(type)) { var props = ts.map(checker.getPropertiesOfType(type), function (prop) { var initializer = prop.valueDeclaration ? tryGetValueFromType(context, checker, importAdder, quotePreference, checker.getTypeAtLocation(prop.valueDeclaration)) : createUndefined(); return ts.factory.createPropertyAssignment(prop.name, initializer); }); return ts.factory.createObjectLiteralExpression(props, /*multiLine*/ true); } if (ts.getObjectFlags(type) & 16 /* ObjectFlags.Anonymous */) { var decl = ts.find(type.symbol.declarations || ts.emptyArray, ts.or(ts.isFunctionTypeNode, ts.isMethodSignature, ts.isMethodDeclaration)); if (decl === undefined) return createUndefined(); var signature = checker.getSignaturesOfType(type, 0 /* SignatureKind.Call */); if (signature === undefined) return createUndefined(); var func = codefix.createSignatureDeclarationFromSignature(213 /* SyntaxKind.FunctionExpression */, context, quotePreference, signature[0], codefix.createStubbedBody(ts.Diagnostics.Function_not_implemented.message, quotePreference), /*name*/ undefined, /*modifiers*/ undefined, /*optional*/ undefined, /*enclosingDeclaration*/ undefined, importAdder); return func !== null && func !== void 0 ? func : createUndefined(); } if (ts.getObjectFlags(type) & 1 /* ObjectFlags.Class */) { var classDeclaration = ts.getClassLikeDeclarationOfSymbol(type.symbol); if (classDeclaration === undefined || ts.hasAbstractModifier(classDeclaration)) return createUndefined(); var constructorDeclaration = ts.getFirstConstructorWithBody(classDeclaration); if (constructorDeclaration && ts.length(constructorDeclaration.parameters)) return createUndefined(); return ts.factory.createNewExpression(ts.factory.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); } return createUndefined(); } function createUndefined() { return ts.factory.createIdentifier("undefined"); } function isObjectLiteralType(type) { return (type.flags & 524288 /* TypeFlags.Object */) && ((ts.getObjectFlags(type) & 128 /* ObjectFlags.ObjectLiteral */) || (type.symbol && ts.tryCast(ts.singleOrUndefined(type.symbol.declarations), ts.isTypeLiteralNode))); } function getUnmatchedAttributes(checker, target, source) { var attrsType = checker.getContextualType(source.attributes); if (attrsType === undefined) return ts.emptyArray; var targetProps = attrsType.getProperties(); if (!ts.length(targetProps)) return ts.emptyArray; var seenNames = new ts.Set(); for (var _i = 0, _a = source.attributes.properties; _i < _a.length; _i++) { var sourceProp = _a[_i]; if (ts.isJsxAttribute(sourceProp)) { seenNames.add(sourceProp.name.escapedText); } if (ts.isJsxSpreadAttribute(sourceProp)) { var type = checker.getTypeAtLocation(sourceProp.expression); for (var _b = 0, _c = type.getProperties(); _b < _c.length; _b++) { var prop = _c[_b]; seenNames.add(prop.escapedName); } } } return ts.filter(targetProps, function (targetProp) { return ts.isIdentifierText(targetProp.name, target, 1 /* LanguageVariant.JSX */) && !((targetProp.flags & 16777216 /* SymbolFlags.Optional */ || ts.getCheckFlags(targetProp) & 48 /* CheckFlags.Partial */) || seenNames.has(targetProp.escapedName)); }); } function tryGetContainingMethodDeclaration(node, callExpression) { if (ts.isTypeLiteralNode(node)) { return undefined; } var declaration = ts.findAncestor(callExpression, function (n) { return ts.isMethodDeclaration(n) || ts.isConstructorDeclaration(n); }); return declaration && declaration.parent === node ? declaration : undefined; } })(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.factory.createNewExpression(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 getCodeActionsToFixNotFoundModule(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: ".concat(context.fixId)); } }); }, }); function getInstallCommand(fileName, packageName) { return { type: "install package", file: fileName, packageName: packageName }; } function tryGetImportedPackageName(sourceFile, pos) { var moduleSpecifierText = ts.tryCast(ts.getTokenAtPosition(sourceFile, pos), ts.isStringLiteral); if (!moduleSpecifierText) return undefined; var moduleName = moduleSpecifierText.text; var packageName = ts.parsePackageName(moduleName).packageName; return ts.isExternalModuleNameRelative(packageName) ? undefined : packageName; } function getTypesPackageNameToInstall(packageName, host, diagCode) { var _a; return diagCode === errorCodeCannotFindModule ? (ts.JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined) : (((_a = host.isKnownTypesPackageName) === null || _a === void 0 ? void 0 : _a.call(host, packageName)) ? ts.getTypesPackageName(packageName) : undefined); } })(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 getCodeActionsToFixClassNotImplementingInheritedMembers(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 getAllCodeActionsToFixClassDoesntImplementInheritedAbstractMember(context) { var seenClassDeclarations = new ts.Map(); 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, sourceFile, context, preferences, importAdder, function (member) { return changeTracker.insertMemberAtStart(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.getSyntacticModifierFlags(ts.first(symbol.getDeclarations())); return !(flags & 8 /* ModifierFlags.Private */) && !!(flags & 128 /* ModifierFlags.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 = new ts.Map(); // 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 !== 108 /* SyntaxKind.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.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.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 getCodeActionsToEnableExperimentalDecorators(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.factory.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 getCodeActionsToFixEnableJsxFlag(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.factory.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_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher.code, ts.Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher.code, ], getCodeActions: function getCodeActionsToFixModuleAndTarget(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.factory.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 /* ScriptTarget.ES2017 */ || target > 99 /* ScriptTarget.ESNext */; if (targetOutOfRange) { var changes = ts.textChanges.ChangeTracker.with(context, function (tracker) { var configObject = ts.getTsConfigObjectLiteralExpression(configFile); if (!configObject) return; var options = [["target", ts.factory.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.factory.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 = "fixPropertyAssignment"; var errorCodes = [ ts.Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern.code ]; codefix.registerCodeFix({ errorCodes: errorCodes, fixIds: [fixId], getCodeActions: function (context) { var sourceFile = context.sourceFile, span = context.span; var property = getProperty(sourceFile, span.start); var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, property); }); return [codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Change_0_to_1, "=", ":"], fixId, [ts.Diagnostics.Switch_each_misused_0_to_1, "=", ":"])]; }, getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return doChange(changes, diag.file, getProperty(diag.file, diag.start)); }); } }); function doChange(changes, sourceFile, node) { changes.replaceNode(sourceFile, node, ts.factory.createPropertyAssignment(node.name, node.objectAssignmentInitializer)); } function getProperty(sourceFile, pos) { return ts.cast(ts.getTokenAtPosition(sourceFile, pos).parent, ts.isShorthandPropertyAssignment); } })(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 === 94 /* SyntaxKind.ExtendsKeyword */ ? { extendsToken: extendsToken, heritageClauses: heritageClauses } : undefined; } function doChanges(changes, sourceFile, extendsToken, heritageClauses) { changes.replaceNode(sourceFile, extendsToken, ts.factory.createToken(117 /* SyntaxKind.ImplementsKeyword */)); // If there is already an implements clause, replace the implements keyword with a comma. if (heritageClauses.length === 2 && heritageClauses[0].token === 94 /* SyntaxKind.ExtendsKeyword */ && heritageClauses[1].token === 117 /* SyntaxKind.ImplementsKeyword */) { var implementsToken = heritageClauses[1].getFirstToken(); var implementsFullStart = implementsToken.getFullStart(); changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, ts.factory.createToken(27 /* SyntaxKind.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_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression.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) || ts.isPrivateIdentifier(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.factory.createPropertyAccessExpression(className ? ts.factory.createIdentifier(className) : ts.factory.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] : "{".concat(ts.quote(sourceFile, preferences, character), "}"); 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 deleteUnmatchedParameter = "deleteUnmatchedParameter"; var renameUnmatchedParameter = "renameUnmatchedParameter"; var errorCodes = [ ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name.code, ]; codefix.registerCodeFix({ fixIds: [deleteUnmatchedParameter, renameUnmatchedParameter], errorCodes: errorCodes, getCodeActions: function getCodeActionsToFixUnmatchedParameter(context) { var sourceFile = context.sourceFile, span = context.span; var actions = []; var info = getInfo(sourceFile, span.start); if (info) { ts.append(actions, getDeleteAction(context, info)); ts.append(actions, getRenameAction(context, info)); return actions; } return undefined; }, getAllCodeActions: function getAllCodeActionsToFixUnmatchedParameter(context) { var tagsToSignature = new ts.Map(); return codefix.createCombinedCodeActions(ts.textChanges.ChangeTracker.with(context, function (changes) { codefix.eachDiagnostic(context, errorCodes, function (_a) { var file = _a.file, start = _a.start; var info = getInfo(file, start); if (info) { tagsToSignature.set(info.signature, ts.append(tagsToSignature.get(info.signature), info.jsDocParameterTag)); } }); tagsToSignature.forEach(function (tags, signature) { if (context.fixId === deleteUnmatchedParameter) { var tagsSet_1 = new ts.Set(tags); changes.filterJSDocTags(signature.getSourceFile(), signature, function (t) { return !tagsSet_1.has(t); }); } }); })); } }); function getDeleteAction(context, _a) { var name = _a.name, signature = _a.signature, jsDocParameterTag = _a.jsDocParameterTag; var changes = ts.textChanges.ChangeTracker.with(context, function (changeTracker) { return changeTracker.filterJSDocTags(context.sourceFile, signature, function (t) { return t !== jsDocParameterTag; }); }); return codefix.createCodeFixAction(deleteUnmatchedParameter, changes, [ts.Diagnostics.Delete_unused_param_tag_0, name.getText(context.sourceFile)], deleteUnmatchedParameter, ts.Diagnostics.Delete_all_unused_param_tags); } function getRenameAction(context, _a) { var name = _a.name, signature = _a.signature, jsDocParameterTag = _a.jsDocParameterTag; if (!ts.length(signature.parameters)) return undefined; var sourceFile = context.sourceFile; var tags = ts.getJSDocTags(signature); var names = new ts.Set(); for (var _i = 0, tags_2 = tags; _i < tags_2.length; _i++) { var tag = tags_2[_i]; if (ts.isJSDocParameterTag(tag) && ts.isIdentifier(tag.name)) { names.add(tag.name.escapedText); } } // @todo - match to all available names instead to the first parameter name // @see /codeFixRenameUnmatchedParameter3.ts var parameterName = ts.firstDefined(signature.parameters, function (p) { return ts.isIdentifier(p.name) && !names.has(p.name.escapedText) ? p.name.getText(sourceFile) : undefined; }); if (parameterName === undefined) return undefined; var newJSDocParameterTag = ts.factory.updateJSDocParameterTag(jsDocParameterTag, jsDocParameterTag.tagName, ts.factory.createIdentifier(parameterName), jsDocParameterTag.isBracketed, jsDocParameterTag.typeExpression, jsDocParameterTag.isNameFirst, jsDocParameterTag.comment); var changes = ts.textChanges.ChangeTracker.with(context, function (changeTracker) { return changeTracker.replaceJSDocComment(sourceFile, signature, ts.map(tags, function (t) { return t === jsDocParameterTag ? newJSDocParameterTag : t; })); }); return codefix.createCodeFixActionWithoutFixAll(renameUnmatchedParameter, changes, [ts.Diagnostics.Rename_param_tag_name_0_to_1, name.getText(sourceFile), parameterName]); } function getInfo(sourceFile, pos) { var token = ts.getTokenAtPosition(sourceFile, pos); if (token.parent && ts.isJSDocParameterTag(token.parent) && ts.isIdentifier(token.parent.name)) { var jsDocParameterTag = token.parent; var signature = ts.getHostSignatureFromJSDoc(jsDocParameterTag); if (signature) { return { signature: signature, name: token.parent.name, jsDocParameterTag: jsDocParameterTag }; } } return undefined; } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixId = "fixUnreferenceableDecoratorMetadata"; var errorCodes = [ts.Diagnostics.A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled.code]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var importDeclaration = getImportDeclaration(context.sourceFile, context.program, context.span.start); if (!importDeclaration) return; var namespaceChanges = ts.textChanges.ChangeTracker.with(context, function (t) { return importDeclaration.kind === 270 /* SyntaxKind.ImportSpecifier */ && doNamespaceImportChange(t, context.sourceFile, importDeclaration, context.program); }); var typeOnlyChanges = ts.textChanges.ChangeTracker.with(context, function (t) { return doTypeOnlyImportChange(t, context.sourceFile, importDeclaration, context.program); }); var actions; if (namespaceChanges.length) { actions = ts.append(actions, codefix.createCodeFixActionWithoutFixAll(fixId, namespaceChanges, ts.Diagnostics.Convert_named_imports_to_namespace_import)); } if (typeOnlyChanges.length) { actions = ts.append(actions, codefix.createCodeFixActionWithoutFixAll(fixId, typeOnlyChanges, ts.Diagnostics.Convert_to_type_only_import)); } return actions; }, fixIds: [fixId], }); function getImportDeclaration(sourceFile, program, start) { var identifier = ts.tryCast(ts.getTokenAtPosition(sourceFile, start), ts.isIdentifier); if (!identifier || identifier.parent.kind !== 178 /* SyntaxKind.TypeReference */) return; var checker = program.getTypeChecker(); var symbol = checker.getSymbolAtLocation(identifier); return ts.find((symbol === null || symbol === void 0 ? void 0 : symbol.declarations) || ts.emptyArray, ts.or(ts.isImportClause, ts.isImportSpecifier, ts.isImportEqualsDeclaration)); } // Converts the import declaration of the offending import to a type-only import, // only if it can be done without affecting other imported names. If the conversion // cannot be done cleanly, we could offer to *extract* the offending import to a // new type-only import declaration, but honestly I doubt anyone will ever use this // codefix at all, so it's probably not worth the lines of code. function doTypeOnlyImportChange(changes, sourceFile, importDeclaration, program) { if (importDeclaration.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { changes.insertModifierBefore(sourceFile, 152 /* SyntaxKind.TypeKeyword */, importDeclaration.name); return; } var importClause = importDeclaration.kind === 267 /* SyntaxKind.ImportClause */ ? importDeclaration : importDeclaration.parent.parent; if (importClause.name && importClause.namedBindings) { // Cannot convert an import with a default import and named bindings to type-only // (it's a grammar error). return; } var checker = program.getTypeChecker(); var importsValue = !!ts.forEachImportClauseDeclaration(importClause, function (decl) { if (ts.skipAlias(decl.symbol, checker).flags & 111551 /* SymbolFlags.Value */) return true; }); if (importsValue) { // Assume that if someone wrote a non-type-only import that includes some values, // they intend to use those values in value positions, even if they haven't yet. // Don't convert it to type-only. return; } changes.insertModifierBefore(sourceFile, 152 /* SyntaxKind.TypeKeyword */, importClause); } function doNamespaceImportChange(changes, sourceFile, importDeclaration, program) { ts.refactor.doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, importDeclaration.parent); } })(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 fixIdDeleteImports = "unusedIdentifier_deleteImports"; 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, cancellationToken = context.cancellationToken; 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 /* SyntaxKind.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 [codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Remove_import_from_0, ts.showModuleSpecifier(importDecl)], fixIdDeleteImports, ts.Diagnostics.Delete_all_unused_imports)]; } else if (isImport(token)) { var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(sourceFile, token, t, checker, sourceFiles, program, cancellationToken, /*isFixAll*/ false); }); if (deletion.length) { return [codefix.createCodeFixAction(fixName, deletion, [ts.Diagnostics.Remove_unused_declaration_for_Colon_0, token.getText(sourceFile)], fixIdDeleteImports, ts.Diagnostics.Delete_all_unused_imports)]; } } if (ts.isObjectBindingPattern(token.parent) || ts.isArrayBindingPattern(token.parent)) { if (ts.isParameter(token.parent.parent)) { var elements = token.parent.elements; var diagnostic = [ elements.length > 1 ? ts.Diagnostics.Remove_unused_declarations_for_Colon_0 : ts.Diagnostics.Remove_unused_declaration_for_Colon_0, ts.map(elements, function (e) { return e.getText(sourceFile); }).join(", ") ]; return [ createDeleteFix(ts.textChanges.ChangeTracker.with(context, function (t) { return deleteDestructuringElements(t, sourceFile, token.parent); }), diagnostic) ]; } return [ createDeleteFix(ts.textChanges.ChangeTracker.with(context, function (t) { return t.delete(sourceFile, token.parent.parent); }), ts.Diagnostics.Remove_unused_destructuring_declaration) ]; } if (canDeleteEntireVariableStatement(sourceFile, token)) { return [ createDeleteFix(ts.textChanges.ChangeTracker.with(context, function (t) { return deleteEntireVariableStatement(t, sourceFile, token.parent); }), ts.Diagnostics.Remove_variable_statement) ]; } var result = []; if (token.kind === 137 /* SyntaxKind.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, program, cancellationToken, /*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, fixIdDeleteImports, fixIdInfer], getAllCodeActions: function (context) { var sourceFile = context.sourceFile, program = context.program, cancellationToken = context.cancellationToken; 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 fixIdDeleteImports: { var importDecl = tryGetFullImport(token); if (importDecl) { changes.delete(sourceFile, importDecl); } else if (isImport(token)) { tryDeleteDeclaration(sourceFile, token, changes, checker, sourceFiles, program, cancellationToken, /*isFixAll*/ true); } break; } case fixIdDelete: { if (token.kind === 137 /* SyntaxKind.InferKeyword */ || isImport(token)) { break; // Can't delete } else if (ts.isJSDocTemplateTag(token)) { changes.delete(sourceFile, token); } else if (token.kind === 29 /* SyntaxKind.LessThanToken */) { deleteTypeParameters(changes, sourceFile, token); } else if (ts.isObjectBindingPattern(token.parent)) { if (token.parent.parent.initializer) { break; } else if (!ts.isParameter(token.parent.parent) || isNotProvidedArguments(token.parent.parent, checker, sourceFiles)) { changes.delete(sourceFile, token.parent.parent); } } else if (ts.isArrayBindingPattern(token.parent.parent) && token.parent.parent.parent.initializer) { break; } else if (canDeleteEntireVariableStatement(sourceFile, token)) { deleteEntireVariableStatement(changes, sourceFile, token.parent); } else { tryDeleteDeclaration(sourceFile, token, changes, checker, sourceFiles, program, cancellationToken, /*isFixAll*/ true); } break; } case fixIdInfer: if (token.kind === 137 /* SyntaxKind.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.factory.createKeywordTypeNode(155 /* SyntaxKind.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")); } function isImport(token) { return token.kind === 100 /* SyntaxKind.ImportKeyword */ || token.kind === 79 /* SyntaxKind.Identifier */ && (token.parent.kind === 270 /* SyntaxKind.ImportSpecifier */ || token.parent.kind === 267 /* SyntaxKind.ImportClause */); } /** Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing. */ function tryGetFullImport(token) { return token.kind === 100 /* SyntaxKind.ImportKeyword */ ? ts.tryCast(token.parent, ts.isImportDeclaration) : undefined; } function canDeleteEntireVariableStatement(sourceFile, token) { return ts.isVariableDeclarationList(token.parent) && ts.first(token.parent.getChildren(sourceFile)) === token; } function deleteEntireVariableStatement(changes, sourceFile, node) { changes.delete(sourceFile, node.parent.kind === 237 /* SyntaxKind.VariableStatement */ ? node.parent : node); } function deleteDestructuringElements(changes, sourceFile, node) { ts.forEach(node.elements, function (n) { return changes.delete(sourceFile, n); }); } 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 === 137 /* SyntaxKind.InferKeyword */) { token = ts.cast(token.parent, ts.isInferTypeNode).typeParameter.name; } if (ts.isIdentifier(token) && canPrefix(token)) { changes.replaceNode(sourceFile, token, ts.factory.createIdentifier("_".concat(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.factory.createIdentifier("_".concat(tag.name.text))); } }); } } } function canPrefix(token) { switch (token.parent.kind) { case 164 /* SyntaxKind.Parameter */: case 163 /* SyntaxKind.TypeParameter */: return true; case 254 /* SyntaxKind.VariableDeclaration */: { var varDecl = token.parent; switch (varDecl.parent.parent.kind) { case 244 /* SyntaxKind.ForOfStatement */: case 243 /* SyntaxKind.ForInStatement */: return true; } } } return false; } function tryDeleteDeclaration(sourceFile, token, changes, checker, sourceFiles, program, cancellationToken, isFixAll) { tryDeleteDeclarationWorker(token, changes, sourceFile, checker, sourceFiles, program, cancellationToken, isFixAll); if (ts.isIdentifier(token)) { ts.FindAllReferences.Core.eachSymbolReferenceInFile(token, checker, sourceFile, function (ref) { if (ts.isPropertyAccessExpression(ref.parent) && ref.parent.name === ref) ref = ref.parent; if (!isFixAll && mayDeleteExpression(ref)) { changes.delete(sourceFile, ref.parent.parent); } }); } } function tryDeleteDeclarationWorker(token, changes, sourceFile, checker, sourceFiles, program, cancellationToken, isFixAll) { var parent = token.parent; if (ts.isParameter(parent)) { tryDeleteParameter(changes, sourceFile, parent, checker, sourceFiles, program, cancellationToken, isFixAll); } else if (!(isFixAll && ts.isIdentifier(token) && ts.FindAllReferences.Core.isSymbolReferencedInFile(token, checker, sourceFile))) { var node = ts.isImportClause(parent) ? token : ts.isComputedPropertyName(parent) ? parent.parent : parent; ts.Debug.assert(node !== sourceFile, "should not delete whole source file"); changes.delete(sourceFile, node); } } function tryDeleteParameter(changes, sourceFile, parameter, checker, sourceFiles, program, cancellationToken, isFixAll) { if (isFixAll === void 0) { isFixAll = false; } if (mayDeleteParameter(checker, sourceFile, parameter, sourceFiles, program, cancellationToken, isFixAll)) { if (parameter.modifiers && parameter.modifiers.length > 0 && (!ts.isIdentifier(parameter.name) || ts.FindAllReferences.Core.isSymbolReferencedInFile(parameter.name, checker, sourceFile))) { parameter.modifiers.forEach(function (modifier) { return changes.deleteModifier(sourceFile, modifier); }); } else if (!parameter.initializer && isNotProvidedArguments(parameter, checker, sourceFiles)) { changes.delete(sourceFile, parameter); } } } function isNotProvidedArguments(parameter, checker, sourceFiles) { var index = parameter.parent.parameters.indexOf(parameter); // Just in case the call didn't provide enough arguments. return !ts.FindAllReferences.Core.someSignatureUsage(parameter.parent, sourceFiles, checker, function (_, call) { return !call || call.arguments.length > index; }); } function mayDeleteParameter(checker, sourceFile, parameter, sourceFiles, program, cancellationToken, isFixAll) { var parent = parameter.parent; switch (parent.kind) { case 169 /* SyntaxKind.MethodDeclaration */: case 171 /* SyntaxKind.Constructor */: var index = parent.parameters.indexOf(parameter); var referent = ts.isMethodDeclaration(parent) ? parent.name : parent; var entries = ts.FindAllReferences.Core.getReferencedSymbolsForNode(parent.pos, referent, program, sourceFiles, cancellationToken); if (entries) { for (var _i = 0, entries_2 = entries; _i < entries_2.length; _i++) { var entry = entries_2[_i]; for (var _a = 0, _b = entry.references; _a < _b.length; _a++) { var reference = _b[_a]; if (reference.kind === 1 /* FindAllReferences.EntryKind.Node */) { // argument in super(...) var isSuperCall_1 = ts.isSuperKeyword(reference.node) && ts.isCallExpression(reference.node.parent) && reference.node.parent.arguments.length > index; // argument in super.m(...) var isSuperMethodCall = ts.isPropertyAccessExpression(reference.node.parent) && ts.isSuperKeyword(reference.node.parent.expression) && ts.isCallExpression(reference.node.parent.parent) && reference.node.parent.parent.arguments.length > index; // parameter in overridden or overriding method var isOverriddenMethod = (ts.isMethodDeclaration(reference.node.parent) || ts.isMethodSignature(reference.node.parent)) && reference.node.parent !== parameter.parent && reference.node.parent.parameters.length > index; if (isSuperCall_1 || isSuperMethodCall || isOverriddenMethod) return false; } } } } return true; case 256 /* SyntaxKind.FunctionDeclaration */: { if (parent.name && isCallbackLike(checker, sourceFile, parent.name)) { return isLastParameter(parent, parameter, isFixAll); } return true; } case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.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. return isLastParameter(parent, parameter, isFixAll); case 173 /* SyntaxKind.SetAccessor */: // Setter must have a parameter return false; case 172 /* SyntaxKind.GetAccessor */: // Getter cannot have parameters return true; default: return ts.Debug.failBadSyntaxKind(parent); } } function isCallbackLike(checker, sourceFile, name) { return !!ts.FindAllReferences.Core.eachSymbolReferenceInFile(name, checker, sourceFile, function (reference) { return ts.isIdentifier(reference) && ts.isCallExpression(reference.parent) && reference.parent.arguments.indexOf(reference) >= 0; }); } function isLastParameter(func, parameter, isFixAll) { var parameters = func.parameters; var index = parameters.indexOf(parameter); ts.Debug.assert(index !== -1, "The parameter should already be in the list"); return isFixAll ? parameters.slice(index + 1).every(function (p) { return ts.isIdentifier(p.name) && !p.symbol.isReferenced; }) : index === parameters.length - 1; } function mayDeleteExpression(node) { return ((ts.isBinaryExpression(node.parent) && node.parent.left === node) || ((ts.isPostfixUnaryExpression(node.parent) || ts.isPrefixUnaryExpression(node.parent)) && node.parent.operand === node)) && ts.isExpressionStatement(node.parent.parent); } })(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 syntacticDiagnostics = context.program.getSyntacticDiagnostics(context.sourceFile, context.cancellationToken); if (syntacticDiagnostics.length) return; 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 239 /* SyntaxKind.IfStatement */: if (container.elseStatement) { if (ts.isBlock(statement.parent)) { break; } else { changes.replaceNode(sourceFile, statement, ts.factory.createBlock(ts.emptyArray)); } return; } // falls through case 241 /* SyntaxKind.WhileStatement */: case 242 /* SyntaxKind.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 /* SyntaxKind.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 === 314 /* SyntaxKind.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 /* TypeFlags.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 === 314 /* SyntaxKind.JSDocNullableType */ && fixId === fixIdNullable ? checker.getNullableType(type, 32768 /* TypeFlags.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 229 /* SyntaxKind.AsExpression */: case 174 /* SyntaxKind.CallSignature */: case 175 /* SyntaxKind.ConstructSignature */: case 256 /* SyntaxKind.FunctionDeclaration */: case 172 /* SyntaxKind.GetAccessor */: case 176 /* SyntaxKind.IndexSignature */: case 195 /* SyntaxKind.MappedType */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: case 164 /* SyntaxKind.Parameter */: case 167 /* SyntaxKind.PropertyDeclaration */: case 166 /* SyntaxKind.PropertySignature */: case 173 /* SyntaxKind.SetAccessor */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 211 /* SyntaxKind.TypeAssertionExpression */: case 254 /* SyntaxKind.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_this_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, "".concat(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.for_await_loops_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules.code, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_to_write_this_in_an_async_function.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 getAllCodeActionsToFixAwaitInSyncFunction(context) { var seen = new ts.Map(); 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 169 /* SyntaxKind.MethodDeclaration */: insertBefore = containingFunction.name; break; case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: insertBefore = ts.findChildOfKind(containingFunction, 98 /* SyntaxKind.FunctionKeyword */, sourceFile); break; case 214 /* SyntaxKind.ArrowFunction */: var kind = containingFunction.typeParameters ? 29 /* SyntaxKind.LessThanToken */ : 20 /* SyntaxKind.OpenParenToken */; insertBefore = ts.findChildOfKind(containingFunction, kind, 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 !== 79 /* SyntaxKind.Identifier */ || entityName.text !== "Promise") { changes.replaceNode(sourceFile, returnType, ts.factory.createTypeReferenceNode("Promise", ts.factory.createNodeArray([returnType]))); } } changes.insertModifierBefore(sourceFile, 131 /* SyntaxKind.AsyncKeyword */, insertBefore); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var errorCodes = [ ts.Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property.code, ts.Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor.code, ]; var fixId = "fixPropertyOverrideAccessor"; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var edits = doChange(context.sourceFile, context.span.start, context.span.length, context.errorCode, context); if (edits) { return [codefix.createCodeFixAction(fixId, edits, ts.Diagnostics.Generate_get_and_set_accessors, fixId, ts.Diagnostics.Generate_get_and_set_accessors_for_all_overriding_properties)]; } }, fixIds: [fixId], getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var edits = doChange(diag.file, diag.start, diag.length, diag.code, context); if (edits) { for (var _i = 0, edits_2 = edits; _i < edits_2.length; _i++) { var edit = edits_2[_i]; changes.pushRaw(context.sourceFile, edit); } } }); }, }); function doChange(file, start, length, code, context) { var startPosition; var endPosition; if (code === ts.Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property.code) { startPosition = start; endPosition = start + length; } else if (code === ts.Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor.code) { var checker = context.program.getTypeChecker(); var node = ts.getTokenAtPosition(file, start).parent; ts.Debug.assert(ts.isAccessor(node), "error span of fixPropertyOverrideAccessor should only be on an accessor"); var containingClass = node.parent; ts.Debug.assert(ts.isClassLike(containingClass), "erroneous accessors should only be inside classes"); var base = ts.singleOrUndefined(codefix.getAllSupers(containingClass, checker)); if (!base) return []; var name = ts.unescapeLeadingUnderscores(ts.getTextOfPropertyName(node.name)); var baseProp = checker.getPropertyOfType(checker.getTypeAtLocation(base), name); if (!baseProp || !baseProp.valueDeclaration) return []; startPosition = baseProp.valueDeclaration.pos; endPosition = baseProp.valueDeclaration.end; file = ts.getSourceFileOfNode(baseProp.valueDeclaration); } else { ts.Debug.fail("fixPropertyOverrideAccessor codefix got unexpected error code " + code); } return codefix.generateAccessorFromProperty(file, context.program, startPosition, endPosition, context, ts.Diagnostics.Generate_get_and_set_accessors.message); } })(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), ts.getTextOfNode(name)], 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 !== 79 /* SyntaxKind.Identifier */ && token.kind !== 25 /* SyntaxKind.DotDotDotToken */ && token.kind !== 108 /* SyntaxKind.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.factory.createJSDocTypeTag(/*tagName*/ undefined, ts.factory.createJSDocTypeExpression(typeNode), /*comment*/ undefined); changes.addJSDocTags(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, ts.getSourceFileOfNode(symbol.valueDeclaration), 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 /* SyntaxKind.OpenParenToken */, sourceFile); if (needParens) changes.insertNodeBefore(sourceFile, ts.first(containingFunction.parameters), ts.factory.createToken(20 /* SyntaxKind.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.factory.createToken(21 /* SyntaxKind.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) { changes.addJSDocTags(sourceFile, containingFunction, [ ts.factory.createJSDocThisTag(/*tagName*/ undefined, ts.factory.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 !== 166 /* SyntaxKind.PropertySignature */) { var parent = ts.isVariableDeclaration(declaration) ? ts.tryCast(declaration.parent.parent, ts.isVariableStatement) : declaration; if (!parent) { return; } var typeExpression = ts.factory.createJSDocTypeExpression(typeNode); var typeTag = ts.isGetAccessorDeclaration(declaration) ? ts.factory.createJSDocReturnTag(/*tagName*/ undefined, typeExpression, /*comment*/ undefined) : ts.factory.createJSDocTypeTag(/*tagName*/ undefined, typeExpression, /*comment*/ undefined); changes.addJSDocTags(sourceFile, parent, [typeTag]); } else if (!tryReplaceImportTypeNodeWithAutoImport(typeNode, declaration, sourceFile, changes, importAdder, ts.getEmitScriptTarget(program.getCompilerOptions()))) { changes.tryInsertTypeAnnotation(sourceFile, declaration, typeNode); } } } function tryReplaceImportTypeNodeWithAutoImport(typeNode, declaration, sourceFile, changes, importAdder, scriptTarget) { var importableReference = codefix.tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget); if (importableReference && changes.tryInsertTypeAnnotation(sourceFile, declaration, importableReference.typeNode)) { 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 inferences = 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); if (typeNode) { var name = ts.factory.cloneNode(param.name); ts.setEmitFlags(name, 1536 /* EmitFlags.NoComments */ | 2048 /* EmitFlags.NoNestedComments */); return { name: ts.factory.cloneNode(param.name), param: param, isOptional: !!inference.isOptional, typeNode: typeNode }; } }); if (!inferences.length) { return; } if (ts.isArrowFunction(signature) || ts.isFunctionExpression(signature)) { var needParens = ts.isArrowFunction(signature) && !ts.findChildOfKind(signature, 20 /* SyntaxKind.OpenParenToken */, sourceFile); if (needParens) { changes.insertNodeBefore(sourceFile, ts.first(signature.parameters), ts.factory.createToken(20 /* SyntaxKind.OpenParenToken */)); } ts.forEach(inferences, function (_a) { var typeNode = _a.typeNode, param = _a.param; var typeTag = ts.factory.createJSDocTypeTag(/*tagName*/ undefined, ts.factory.createJSDocTypeExpression(typeNode)); var jsDoc = ts.factory.createJSDocComment(/*comment*/ undefined, [typeTag]); changes.insertNodeAt(sourceFile, param.getStart(sourceFile), jsDoc, { suffix: " " }); }); if (needParens) { changes.insertNodeAfter(sourceFile, ts.last(signature.parameters), ts.factory.createToken(21 /* SyntaxKind.CloseParenToken */)); } } else { var paramTags = ts.map(inferences, function (_a) { var name = _a.name, typeNode = _a.typeNode, isOptional = _a.isOptional; return ts.factory.createJSDocParameterTag(/*tagName*/ undefined, name, /*isBracketed*/ !!isOptional, ts.factory.createJSDocTypeExpression(typeNode), /* isNameFirst */ false, /*comment*/ undefined); }); changes.addJSDocTags(sourceFile, signature, paramTags); } } 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 /* FindAllReferences.EntryKind.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 171 /* SyntaxKind.Constructor */: searchToken = ts.findChildOfKind(containingFunction, 134 /* SyntaxKind.ConstructorKeyword */, sourceFile); break; case 214 /* SyntaxKind.ArrowFunction */: case 213 /* SyntaxKind.FunctionExpression */: var parent = containingFunction.parent; searchToken = (ts.isVariableDeclaration(parent) || ts.isPropertyDeclaration(parent)) && ts.isIdentifier(parent.name) ? parent.name : containingFunction.name; break; case 256 /* SyntaxKind.FunctionDeclaration */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: 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 = new ts.Map(); 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 = new ts.Map(); 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, // clear type cache }; } 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_3 = references; _i < references_3.length; _i++) { var reference = references_3[_i]; cancellationToken.throwIfCancellationRequested(); calculateUsageOfNode(reference, usage); } var calls = __spreadArray(__spreadArray([], usage.constructs || [], true), usage.calls || [], true); 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_4 = references; _i < references_4.length; _i++) { var reference = references_4[_i]; cancellationToken.throwIfCancellationRequested(); calculateUsageOfNode(reference, usage); } return combineTypes(usage.candidateThisTypes || ts.emptyArray); } function inferTypesFromReferencesSingle(references) { var usage = createEmptyUsage(); for (var _i = 0, references_5 = references; _i < references_5.length; _i++) { var reference = references_5[_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 238 /* SyntaxKind.ExpressionStatement */: inferTypeFromExpressionStatement(node, usage); break; case 220 /* SyntaxKind.PostfixUnaryExpression */: usage.isNumber = true; break; case 219 /* SyntaxKind.PrefixUnaryExpression */: inferTypeFromPrefixUnaryExpression(node.parent, usage); break; case 221 /* SyntaxKind.BinaryExpression */: inferTypeFromBinaryExpression(node, node.parent, usage); break; case 289 /* SyntaxKind.CaseClause */: case 290 /* SyntaxKind.DefaultClause */: inferTypeFromSwitchStatementLabel(node.parent, usage); break; case 208 /* SyntaxKind.CallExpression */: case 209 /* SyntaxKind.NewExpression */: if (node.parent.expression === node) { inferTypeFromCallExpression(node.parent, usage); } else { inferTypeFromContextualType(node, usage); } break; case 206 /* SyntaxKind.PropertyAccessExpression */: inferTypeFromPropertyAccessExpression(node.parent, usage); break; case 207 /* SyntaxKind.ElementAccessExpression */: inferTypeFromPropertyElementExpression(node.parent, node, usage); break; case 296 /* SyntaxKind.PropertyAssignment */: case 297 /* SyntaxKind.ShorthandPropertyAssignment */: inferTypeFromPropertyAssignment(node.parent, usage); break; case 167 /* SyntaxKind.PropertyDeclaration */: inferTypeFromPropertyDeclaration(node.parent, usage); break; case 254 /* SyntaxKind.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 /* SyntaxKind.PlusPlusToken */: case 46 /* SyntaxKind.MinusMinusToken */: case 40 /* SyntaxKind.MinusToken */: case 54 /* SyntaxKind.TildeToken */: usage.isNumber = true; break; case 39 /* SyntaxKind.PlusToken */: usage.isNumberOrString = true; break; // case SyntaxKind.ExclamationToken: // no inferences here; } } function inferTypeFromBinaryExpression(node, parent, usage) { switch (parent.operatorToken.kind) { // ExponentiationOperator case 42 /* SyntaxKind.AsteriskAsteriskToken */: // MultiplicativeOperator // falls through case 41 /* SyntaxKind.AsteriskToken */: case 43 /* SyntaxKind.SlashToken */: case 44 /* SyntaxKind.PercentToken */: // ShiftOperator // falls through case 47 /* SyntaxKind.LessThanLessThanToken */: case 48 /* SyntaxKind.GreaterThanGreaterThanToken */: case 49 /* SyntaxKind.GreaterThanGreaterThanGreaterThanToken */: // BitwiseOperator // falls through case 50 /* SyntaxKind.AmpersandToken */: case 51 /* SyntaxKind.BarToken */: case 52 /* SyntaxKind.CaretToken */: // CompoundAssignmentOperator // falls through case 65 /* SyntaxKind.MinusEqualsToken */: case 67 /* SyntaxKind.AsteriskAsteriskEqualsToken */: case 66 /* SyntaxKind.AsteriskEqualsToken */: case 68 /* SyntaxKind.SlashEqualsToken */: case 69 /* SyntaxKind.PercentEqualsToken */: case 73 /* SyntaxKind.AmpersandEqualsToken */: case 74 /* SyntaxKind.BarEqualsToken */: case 78 /* SyntaxKind.CaretEqualsToken */: case 70 /* SyntaxKind.LessThanLessThanEqualsToken */: case 72 /* SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken */: case 71 /* SyntaxKind.GreaterThanGreaterThanEqualsToken */: // AdditiveOperator // falls through case 40 /* SyntaxKind.MinusToken */: // RelationalOperator // falls through case 29 /* SyntaxKind.LessThanToken */: case 32 /* SyntaxKind.LessThanEqualsToken */: case 31 /* SyntaxKind.GreaterThanToken */: case 33 /* SyntaxKind.GreaterThanEqualsToken */: var operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); if (operandType.flags & 1056 /* TypeFlags.EnumLike */) { addCandidateType(usage, operandType); } else { usage.isNumber = true; } break; case 64 /* SyntaxKind.PlusEqualsToken */: case 39 /* SyntaxKind.PlusToken */: var otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); if (otherOperandType.flags & 1056 /* TypeFlags.EnumLike */) { addCandidateType(usage, otherOperandType); } else if (otherOperandType.flags & 296 /* TypeFlags.NumberLike */) { usage.isNumber = true; } else if (otherOperandType.flags & 402653316 /* TypeFlags.StringLike */) { usage.isString = true; } else if (otherOperandType.flags & 1 /* TypeFlags.Any */) { // do nothing, maybe we'll learn something elsewhere } else { usage.isNumberOrString = true; } break; // AssignmentOperators case 63 /* SyntaxKind.EqualsToken */: case 34 /* SyntaxKind.EqualsEqualsToken */: case 36 /* SyntaxKind.EqualsEqualsEqualsToken */: case 37 /* SyntaxKind.ExclamationEqualsEqualsToken */: case 35 /* SyntaxKind.ExclamationEqualsToken */: addCandidateType(usage, checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left)); break; case 101 /* SyntaxKind.InKeyword */: if (node === parent.left) { usage.isString = true; } break; // LogicalOperator Or NullishCoalescing case 56 /* SyntaxKind.BarBarToken */: case 60 /* SyntaxKind.QuestionQuestionToken */: if (node === parent.left && (node.parent.parent.kind === 254 /* SyntaxKind.VariableDeclaration */ || ts.isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true))) { // var x = x || {}; // TODO: use getFalsyflagsOfType addCandidateType(usage, checker.getTypeAtLocation(parent.right)); } break; case 55 /* SyntaxKind.AmpersandAmpersandToken */: case 27 /* SyntaxKind.CommaToken */: case 102 /* SyntaxKind.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 === 208 /* SyntaxKind.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 = new ts.Map(); } 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 /* TypeFlags.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 /* TypeFlags.Any */ | 16384 /* TypeFlags.Void */)); }, low: function (t) { return !!(t.flags & (1 /* TypeFlags.Any */ | 16384 /* TypeFlags.Void */)); } }, { high: function (t) { return !(t.flags & (98304 /* TypeFlags.Nullable */ | 1 /* TypeFlags.Any */ | 16384 /* TypeFlags.Void */)) && !(ts.getObjectFlags(t) & 16 /* ObjectFlags.Anonymous */); }, low: function (t) { return !!(ts.getObjectFlags(t) & 16 /* ObjectFlags.Anonymous */); } } ]; var good = removeLowPriorityInferences(inferences, priorities); var anons = good.filter(function (i) { return ts.getObjectFlags(i) & 16 /* ObjectFlags.Anonymous */; }); if (anons.length) { good = good.filter(function (i) { return !(ts.getObjectFlags(i) & 16 /* ObjectFlags.Anonymous */); }); good.push(combineAnonymousTypes(anons)); } return checker.getWidenedType(checker.getUnionType(good.map(checker.getBaseTypeOfLiteralType), 2 /* UnionReduction.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, p.valueDeclaration ? checker.getTypeOfSymbolAtLocation(p, p.valueDeclaration) : checker.getAnyType()); } calls.push.apply(calls, checker.getSignaturesOfType(anon, 0 /* SignatureKind.Call */)); constructs.push.apply(constructs, checker.getSignaturesOfType(anon, 1 /* SignatureKind.Construct */)); var stringIndexInfo = checker.getIndexInfoOfType(anon, 0 /* IndexKind.String */); if (stringIndexInfo) { stringIndices.push(stringIndexInfo.type); stringIndexReadonly = stringIndexReadonly || stringIndexInfo.isReadonly; } var numberIndexInfo = checker.getIndexInfoOfType(anon, 1 /* IndexKind.Number */); if (numberIndexInfo) { numberIndices.push(numberIndexInfo.type); numberIndexReadonly = numberIndexReadonly || numberIndexInfo.isReadonly; } } var members = ts.mapEntries(props, function (name, types) { var isOptional = types.length < anons.length ? 16777216 /* SymbolFlags.Optional */ : 0; var s = checker.createSymbol(4 /* SymbolFlags.Property */ | isOptional, name); s.type = checker.getUnionType(types); return [name, s]; }); var indexInfos = []; if (stringIndices.length) indexInfos.push(checker.createIndexInfo(checker.getStringType(), checker.getUnionType(stringIndices), stringIndexReadonly)); if (numberIndices.length) indexInfos.push(checker.createIndexInfo(checker.getNumberType(), checker.getUnionType(numberIndices), numberIndexReadonly)); return checker.createAnonymousType(anons[0].symbol, members, calls, constructs, indexInfos); } 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.constructs) === null || _b === void 0 ? void 0 : _b.length) || usage.stringIndex) { types.push(inferStructuralType(usage)); } var candidateTypes = (usage.candidateTypes || []).map(function (t) { return checker.getBaseTypeOfLiteralType(t); }); var callsType = ((_c = usage.calls) === null || _c === void 0 ? void 0 : _c.length) ? inferStructuralType(usage) : undefined; if (callsType && candidateTypes) { types.push(checker.getUnionType(__spreadArray([callsType], candidateTypes, true), 2 /* UnionReduction.Subtype */)); } else { if (callsType) { types.push(callsType); } if (ts.length(candidateTypes)) { types.push.apply(types, candidateTypes); } } types.push.apply(types, inferNamedTypesFromProperties(usage)); return types; } function inferStructuralType(usage) { var members = new ts.Map(); if (usage.properties) { usage.properties.forEach(function (u, name) { var symbol = checker.createSymbol(4 /* SymbolFlags.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 indexInfos = usage.stringIndex ? [checker.createIndexInfo(checker.getStringType(), combineFromUsage(usage.stringIndex), /*isReadonly*/ false)] : []; return checker.createAnonymousType(/*symbol*/ undefined, members, callSignatures, constructSignatures, indexInfos); } 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 /* SignatureKind.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 /* ObjectFlags.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 /* TypeFlags.UnionOrIntersection */) { return ts.flatMap(genericType.types, function (t) { return inferTypeParameters(t, usageType, typeParameter); }); } else if (ts.getObjectFlags(genericType) & 4 /* ObjectFlags.Reference */ && ts.getObjectFlags(usageType) & 4 /* ObjectFlags.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 /* SignatureKind.Call */); var usageSigs = checker.getSignaturesOfType(usageType, 0 /* SignatureKind.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 = genericParam.valueDeclaration ? checker.getTypeOfSymbolAtLocation(genericParam, genericParam.valueDeclaration) : checker.getAnyType(); var elementType = isRest && checker.getElementTypeOfArrayType(genericParamType); if (elementType) { genericParamType = elementType; } var targetType = usageParam.type || (usageParam.valueDeclaration ? checker.getTypeOfSymbolAtLocation(usageParam, usageParam.valueDeclaration) : checker.getAnyType()); 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, ts.emptyArray); } function getSignatureFromCalls(calls) { var parameters = []; var length = Math.max.apply(Math, calls.map(function (c) { return c.argumentTypes.length; })); var _loop_16 = function (i) { var symbol = checker.createSymbol(1 /* SymbolFlags.FunctionScopedVariable */, ts.escapeLeadingUnderscores("arg".concat(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 /* SymbolFlags.Optional */; } parameters.push(symbol); }; for (var i = 0; i < length; i++) { _loop_16(i); } var returnType = combineFromUsage(combineUsages(calls.map(function (call) { return call.return_; }))); return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, length, 0 /* SignatureFlags.None */); } function addCandidateType(usage, type) { if (type && !(type.flags & 1 /* TypeFlags.Any */) && !(type.flags & 131072 /* TypeFlags.Never */)) { (usage.candidateTypes || (usage.candidateTypes = [])).push(type); } } function addCandidateThisType(usage, type) { if (type && !(type.flags & 1 /* TypeFlags.Any */) && !(type.flags & 131072 /* TypeFlags.Never */)) { (usage.candidateThisTypes || (usage.candidateThisTypes = [])).push(type); } } } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixId = "fixReturnTypeInAsyncFunction"; var errorCodes = [ ts.Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, fixIds: [fixId], getCodeActions: function getCodeActionsToFixReturnTypeInAsyncFunction(context) { var sourceFile = context.sourceFile, program = context.program, span = context.span; var checker = program.getTypeChecker(); var info = getInfo(sourceFile, program.getTypeChecker(), span.start); if (!info) { return undefined; } var returnTypeNode = info.returnTypeNode, returnType = info.returnType, promisedTypeNode = info.promisedTypeNode, promisedType = info.promisedType; var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, returnTypeNode, promisedTypeNode); }); return [codefix.createCodeFixAction(fixId, changes, [ts.Diagnostics.Replace_0_with_Promise_1, checker.typeToString(returnType), checker.typeToString(promisedType)], fixId, ts.Diagnostics.Fix_all_incorrect_return_type_of_an_async_functions)]; }, getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var info = getInfo(diag.file, context.program.getTypeChecker(), diag.start); if (info) { doChange(changes, diag.file, info.returnTypeNode, info.promisedTypeNode); } }); } }); function getInfo(sourceFile, checker, pos) { if (ts.isInJSFile(sourceFile)) { return undefined; } var token = ts.getTokenAtPosition(sourceFile, pos); var func = ts.findAncestor(token, ts.isFunctionLikeDeclaration); var returnTypeNode = func === null || func === void 0 ? void 0 : func.type; if (!returnTypeNode) { return undefined; } var returnType = checker.getTypeFromTypeNode(returnTypeNode); var promisedType = checker.getAwaitedType(returnType) || checker.getVoidType(); var promisedTypeNode = checker.typeToTypeNode(promisedType, /*enclosingDeclaration*/ returnTypeNode, /*flags*/ undefined); if (promisedTypeNode) { return { returnTypeNode: returnTypeNode, returnType: returnType, promisedTypeNode: promisedTypeNode, promisedType: promisedType }; } } function doChange(changes, sourceFile, returnTypeNode, promisedTypeNode) { changes.replaceNode(sourceFile, returnTypeNode, ts.factory.createTypeReferenceNode("Promise", [promisedTypeNode])); } })(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 getCodeActionsToDisableJsDiagnostics(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".concat(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 = new ts.Set(); 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.tryAddToSet(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, sourceFile, 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, sourceFile, context, preferences, importAdder, addClassElement, /* body */ undefined); } } } codefix.createMissingMemberNodes = createMissingMemberNodes; function getNoopSymbolTrackerWithResolver(context) { return { trackSymbol: function () { return false; }, moduleResolverHost: ts.getModuleSpecifierResolverHost(context.program, context.host), }; } codefix.getNoopSymbolTrackerWithResolver = getNoopSymbolTrackerWithResolver; var PreserveOptionalFlags; (function (PreserveOptionalFlags) { PreserveOptionalFlags[PreserveOptionalFlags["Method"] = 1] = "Method"; PreserveOptionalFlags[PreserveOptionalFlags["Property"] = 2] = "Property"; PreserveOptionalFlags[PreserveOptionalFlags["All"] = 3] = "All"; })(PreserveOptionalFlags = codefix.PreserveOptionalFlags || (codefix.PreserveOptionalFlags = {})); /** * `addClassElement` will not be called if we can't figure out a representation for `symbol` in `enclosingDeclaration`. * @param body If defined, this will be the body of the member node passed to `addClassElement`. Otherwise, the body will default to a stub. */ function addNewNodeForMemberSymbol(symbol, enclosingDeclaration, sourceFile, context, preferences, importAdder, addClassElement, body, preserveOptional, isAmbient) { if (preserveOptional === void 0) { preserveOptional = 3 /* PreserveOptionalFlags.All */; } if (isAmbient === void 0) { isAmbient = false; } 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.getEffectiveModifierFlags(declaration)); var modifiers = visibilityModifier ? ts.factory.createNodeArray([visibilityModifier]) : undefined; var type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration)); var optional = !!(symbol.flags & 16777216 /* SymbolFlags.Optional */); var ambient = !!(enclosingDeclaration.flags & 16777216 /* NodeFlags.Ambient */) || isAmbient; var quotePreference = ts.getQuotePreference(sourceFile, preferences); switch (declaration.kind) { case 166 /* SyntaxKind.PropertySignature */: case 167 /* SyntaxKind.PropertyDeclaration */: var flags = quotePreference === 0 /* QuotePreference.Single */ ? 268435456 /* NodeBuilderFlags.UseSingleQuotesForStringLiteralType */ : undefined; var typeNode = checker.typeToTypeNode(type, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context)); if (importAdder) { var importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget); if (importableReference) { typeNode = importableReference.typeNode; importSymbols(importAdder, importableReference.symbols); } } addClassElement(ts.factory.createPropertyDeclaration( /*decorators*/ undefined, modifiers, name, optional && (preserveOptional & 2 /* PreserveOptionalFlags.Property */) ? ts.factory.createToken(57 /* SyntaxKind.QuestionToken */) : undefined, typeNode, /*initializer*/ undefined)); break; case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.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 = tryGetAutoImportableReferenceFromTypeNode(typeNode_1, scriptTarget); if (importableReference) { typeNode_1 = importableReference.typeNode; 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.factory.createGetAccessorDeclaration( /*decorators*/ undefined, modifiers, name, ts.emptyArray, typeNode_1, ambient ? undefined : body || createStubbedMethodBody(quotePreference))); } 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.factory.createSetAccessorDeclaration( /*decorators*/ undefined, modifiers, name, createDummyParameters(1, [parameterName], [typeNode_1], 1, /*inJs*/ false), ambient ? undefined : body || createStubbedMethodBody(quotePreference))); } } break; } case 168 /* SyntaxKind.MethodSignature */: case 169 /* SyntaxKind.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 /* SignatureKind.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(quotePreference, signature, modifiers, name, ambient ? undefined : body || createStubbedMethodBody(quotePreference)); break; } for (var _a = 0, signatures_1 = signatures; _a < signatures_1.length; _a++) { var signature = signatures_1[_a]; // Ensure nodes are fresh so they can have different positions when going through formatting. outputMethod(quotePreference, 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(quotePreference, signature, modifiers, name, body || createStubbedMethodBody(quotePreference)); } else { ts.Debug.assert(declarations.length === signatures.length, "Declarations and signatures should match count"); addClassElement(createMethodImplementingSignatures(checker, context, enclosingDeclaration, signatures, name, optional && !!(preserveOptional & 1 /* PreserveOptionalFlags.Method */), modifiers, quotePreference, body)); } } break; } function outputMethod(quotePreference, signature, modifiers, name, body) { var method = createSignatureDeclarationFromSignature(169 /* SyntaxKind.MethodDeclaration */, context, quotePreference, signature, body, name, modifiers, optional && !!(preserveOptional & 1 /* PreserveOptionalFlags.Method */), enclosingDeclaration, importAdder); if (method) addClassElement(method); } } codefix.addNewNodeForMemberSymbol = addNewNodeForMemberSymbol; function createSignatureDeclarationFromSignature(kind, context, quotePreference, signature, body, name, modifiers, optional, enclosingDeclaration, importAdder) { var program = context.program; var checker = program.getTypeChecker(); var scriptTarget = ts.getEmitScriptTarget(program.getCompilerOptions()); var flags = 1 /* NodeBuilderFlags.NoTruncation */ | 256 /* NodeBuilderFlags.SuppressAnyReturnType */ | 524288 /* NodeBuilderFlags.AllowEmptyTuple */ | (quotePreference === 0 /* QuotePreference.Single */ ? 268435456 /* NodeBuilderFlags.UseSingleQuotesForStringLiteralType */ : 0 /* NodeBuilderFlags.None */); var signatureDeclaration = checker.signatureToSignatureDeclaration(signature, kind, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context)); if (!signatureDeclaration) { return undefined; } var typeParameters = signatureDeclaration.typeParameters; var parameters = signatureDeclaration.parameters; var type = signatureDeclaration.type; if (importAdder) { if (typeParameters) { var newTypeParameters = ts.sameMap(typeParameters, function (typeParameterDecl) { var constraint = typeParameterDecl.constraint; var defaultType = typeParameterDecl.default; if (constraint) { var importableReference = tryGetAutoImportableReferenceFromTypeNode(constraint, scriptTarget); if (importableReference) { constraint = importableReference.typeNode; importSymbols(importAdder, importableReference.symbols); } } if (defaultType) { var importableReference = tryGetAutoImportableReferenceFromTypeNode(defaultType, scriptTarget); if (importableReference) { defaultType = importableReference.typeNode; importSymbols(importAdder, importableReference.symbols); } } return ts.factory.updateTypeParameterDeclaration(typeParameterDecl, typeParameterDecl.modifiers, typeParameterDecl.name, constraint, defaultType); }); if (typeParameters !== newTypeParameters) { typeParameters = ts.setTextRange(ts.factory.createNodeArray(newTypeParameters, typeParameters.hasTrailingComma), typeParameters); } } var newParameters = ts.sameMap(parameters, function (parameterDecl) { var importableReference = tryGetAutoImportableReferenceFromTypeNode(parameterDecl.type, scriptTarget); var type = parameterDecl.type; if (importableReference) { type = importableReference.typeNode; importSymbols(importAdder, importableReference.symbols); } return ts.factory.updateParameterDeclaration(parameterDecl, parameterDecl.decorators, parameterDecl.modifiers, parameterDecl.dotDotDotToken, parameterDecl.name, parameterDecl.questionToken, type, parameterDecl.initializer); }); if (parameters !== newParameters) { parameters = ts.setTextRange(ts.factory.createNodeArray(newParameters, parameters.hasTrailingComma), parameters); } if (type) { var importableReference = tryGetAutoImportableReferenceFromTypeNode(type, scriptTarget); if (importableReference) { type = importableReference.typeNode; importSymbols(importAdder, importableReference.symbols); } } } var questionToken = optional ? ts.factory.createToken(57 /* SyntaxKind.QuestionToken */) : undefined; var asteriskToken = signatureDeclaration.asteriskToken; if (ts.isFunctionExpression(signatureDeclaration)) { return ts.factory.updateFunctionExpression(signatureDeclaration, modifiers, signatureDeclaration.asteriskToken, ts.tryCast(name, ts.isIdentifier), typeParameters, parameters, type, body !== null && body !== void 0 ? body : signatureDeclaration.body); } if (ts.isArrowFunction(signatureDeclaration)) { return ts.factory.updateArrowFunction(signatureDeclaration, modifiers, typeParameters, parameters, type, signatureDeclaration.equalsGreaterThanToken, body !== null && body !== void 0 ? body : signatureDeclaration.body); } if (ts.isMethodDeclaration(signatureDeclaration)) { return ts.factory.updateMethodDeclaration(signatureDeclaration, /* decorators */ undefined, modifiers, asteriskToken, name !== null && name !== void 0 ? name : ts.factory.createIdentifier(""), questionToken, typeParameters, parameters, type, body); } return undefined; } codefix.createSignatureDeclarationFromSignature = createSignatureDeclarationFromSignature; function createSignatureDeclarationFromCallExpression(kind, context, importAdder, call, name, modifierFlags, contextNode) { var quotePreference = ts.getQuotePreference(context.sourceFile, context.preferences); var scriptTarget = ts.getEmitScriptTarget(context.program.getCompilerOptions()); var tracker = getNoopSymbolTrackerWithResolver(context); var checker = context.program.getTypeChecker(); var isJs = ts.isInJSFile(contextNode); var typeArguments = call.typeArguments, args = call.arguments, parent = call.parent; var contextualType = isJs ? undefined : checker.getContextualType(call); 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 types = isJs ? [] : ts.map(args, function (arg) { return typeToAutoImportableTypeNode(checker, importAdder, checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(arg)), contextNode, scriptTarget, /*flags*/ undefined, tracker); }); var modifiers = modifierFlags ? ts.factory.createNodeArray(ts.factory.createModifiersFromModifierFlags(modifierFlags)) : undefined; var asteriskToken = ts.isYieldExpression(parent) ? ts.factory.createToken(41 /* SyntaxKind.AsteriskToken */) : undefined; var typeParameters = isJs || typeArguments === undefined ? undefined : ts.map(typeArguments, function (_, i) { return ts.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, 84 /* CharacterCodes.T */ + typeArguments.length - 1 <= 90 /* CharacterCodes.Z */ ? String.fromCharCode(84 /* CharacterCodes.T */ + i) : "T".concat(i)); }); var parameters = createDummyParameters(args.length, names, types, /*minArgumentCount*/ undefined, isJs); var type = isJs || contextualType === undefined ? undefined : checker.typeToTypeNode(contextualType, contextNode, /*flags*/ undefined, tracker); switch (kind) { case 169 /* SyntaxKind.MethodDeclaration */: return ts.factory.createMethodDeclaration( /*decorators*/ undefined, modifiers, asteriskToken, name, /*questionToken*/ undefined, typeParameters, parameters, type, createStubbedMethodBody(quotePreference)); case 168 /* SyntaxKind.MethodSignature */: return ts.factory.createMethodSignature(modifiers, name, /*questionToken*/ undefined, typeParameters, parameters, type); case 256 /* SyntaxKind.FunctionDeclaration */: return ts.factory.createFunctionDeclaration( /*decorators*/ undefined, modifiers, asteriskToken, name, typeParameters, parameters, type, createStubbedBody(ts.Diagnostics.Function_not_implemented.message, quotePreference)); default: ts.Debug.fail("Unexpected kind"); } } codefix.createSignatureDeclarationFromCallExpression = createSignatureDeclarationFromCallExpression; function typeToAutoImportableTypeNode(checker, importAdder, type, contextNode, scriptTarget, flags, tracker) { var typeNode = checker.typeToTypeNode(type, contextNode, flags, tracker); if (typeNode && ts.isImportTypeNode(typeNode)) { var importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget); if (importableReference) { importSymbols(importAdder, importableReference.symbols); typeNode = importableReference.typeNode; } } // Ensure nodes are fresh so they can have different positions when going through formatting. return ts.getSynthesizedDeepClone(typeNode); } codefix.typeToAutoImportableTypeNode = typeToAutoImportableTypeNode; function createDummyParameters(argCount, names, types, minArgumentCount, inJs) { var parameters = []; for (var i = 0; i < argCount; i++) { var newParameter = ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ names && names[i] || "arg".concat(i), /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? ts.factory.createToken(57 /* SyntaxKind.QuestionToken */) : undefined, /*type*/ inJs ? undefined : types && types[i] || ts.factory.createKeywordTypeNode(155 /* SyntaxKind.UnknownKeyword */), /*initializer*/ undefined); parameters.push(newParameter); } return parameters; } function createMethodImplementingSignatures(checker, context, enclosingDeclaration, signatures, name, optional, modifiers, quotePreference, body) { /** 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 restParameter = ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createToken(25 /* SyntaxKind.DotDotDotToken */), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest", /*questionToken*/ maxNonRestArgs >= minArgumentCount ? ts.factory.createToken(57 /* SyntaxKind.QuestionToken */) : undefined, ts.factory.createArrayTypeNode(ts.factory.createKeywordTypeNode(155 /* SyntaxKind.UnknownKeyword */)), /*initializer*/ undefined); parameters.push(restParameter); } return createStubbedMethod(modifiers, name, optional, /*typeParameters*/ undefined, parameters, getReturnTypeFromSignatures(signatures, checker, context, enclosingDeclaration), quotePreference, body); } function getReturnTypeFromSignatures(signatures, checker, context, enclosingDeclaration) { if (ts.length(signatures)) { var type = checker.getUnionType(ts.map(signatures, checker.getReturnTypeOfSignature)); return checker.typeToTypeNode(type, enclosingDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context)); } } function createStubbedMethod(modifiers, name, optional, typeParameters, parameters, returnType, quotePreference, body) { return ts.factory.createMethodDeclaration( /*decorators*/ undefined, modifiers, /*asteriskToken*/ undefined, name, optional ? ts.factory.createToken(57 /* SyntaxKind.QuestionToken */) : undefined, typeParameters, parameters, returnType, body || createStubbedMethodBody(quotePreference)); } function createStubbedMethodBody(quotePreference) { return createStubbedBody(ts.Diagnostics.Method_not_implemented.message, quotePreference); } function createStubbedBody(text, quotePreference) { return ts.factory.createBlock([ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier("Error"), /*typeArguments*/ undefined, // TODO Handle auto quote preference. [ts.factory.createStringLiteral(text, /*isSingleQuote*/ quotePreference === 0 /* QuotePreference.Single */)]))], /*multiline*/ true); } codefix.createStubbedBody = createStubbedBody; function createVisibilityModifier(flags) { if (flags & 4 /* ModifierFlags.Public */) { return ts.factory.createToken(123 /* SyntaxKind.PublicKeyword */); } else if (flags & 16 /* ModifierFlags.Protected */) { return ts.factory.createToken(122 /* SyntaxKind.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.factory.createObjectLiteralExpression(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.factory.createPropertyAssignment(ts.factory.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 a type node containing '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 tryGetAutoImportableReferenceFromTypeNode(importTypeNode, scriptTarget) { var symbols; var typeNode = ts.visitNode(importTypeNode, visit); if (symbols && typeNode) { return { typeNode: typeNode, symbols: symbols }; } function visit(node) { var _a; if (ts.isLiteralImportTypeNode(node) && node.qualifier) { // Symbol for the left-most thing after the dot var firstIdentifier = ts.getFirstIdentifier(node.qualifier); var name = ts.getNameForExportedSymbol(firstIdentifier.symbol, scriptTarget); var qualifier = name !== firstIdentifier.text ? replaceFirstIdentifierOfEntityName(node.qualifier, ts.factory.createIdentifier(name)) : node.qualifier; symbols = ts.append(symbols, firstIdentifier.symbol); var typeArguments = (_a = node.typeArguments) === null || _a === void 0 ? void 0 : _a.map(visit); return ts.factory.createTypeReferenceNode(qualifier, typeArguments); } return ts.visitEachChild(node, visit, ts.nullTransformationContext); } } codefix.tryGetAutoImportableReferenceFromTypeNode = tryGetAutoImportableReferenceFromTypeNode; function replaceFirstIdentifierOfEntityName(name, newIdentifier) { if (name.kind === 79 /* SyntaxKind.Identifier */) { return newIdentifier; } return ts.factory.createQualifiedName(replaceFirstIdentifierOfEntityName(name.left, newIdentifier), name.right); } function importSymbols(importAdder, symbols) { symbols.forEach(function (s) { return importAdder.addImportFromExportedSymbol(s, /*isValidTypeOnlyUseSite*/ true); }); } codefix.importSymbols = importSymbols; })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { function generateAccessorFromProperty(file, program, start, end, context, _actionName) { var fieldInfo = getAccessorConvertiblePropertyAtPosition(file, program, start, end); if (!fieldInfo || ts.refactor.isRefactorErrorInfo(fieldInfo)) return undefined; var changeTracker = ts.textChanges.ChangeTracker.fromContext(context); var isStatic = fieldInfo.isStatic, isReadonly = fieldInfo.isReadonly, fieldName = fieldInfo.fieldName, accessorName = fieldInfo.accessorName, originalName = fieldInfo.originalName, type = fieldInfo.type, container = fieldInfo.container, declaration = fieldInfo.declaration; ts.suppressLeadingAndTrailingTrivia(fieldName); ts.suppressLeadingAndTrailingTrivia(accessorName); ts.suppressLeadingAndTrailingTrivia(declaration); ts.suppressLeadingAndTrailingTrivia(container); var accessorModifiers; var fieldModifiers; if (ts.isClassLike(container)) { var modifierFlags = ts.getEffectiveModifierFlags(declaration); if (ts.isSourceFileJS(file)) { var modifiers = ts.createModifiers(modifierFlags); accessorModifiers = modifiers; fieldModifiers = modifiers; } else { accessorModifiers = ts.createModifiers(prepareModifierFlagsForAccessor(modifierFlags)); fieldModifiers = ts.createModifiers(prepareModifierFlagsForField(modifierFlags)); } } updateFieldDeclaration(changeTracker, file, declaration, type, fieldName, fieldModifiers); var getAccessor = generateGetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); ts.suppressLeadingAndTrailingTrivia(getAccessor); insertAccessor(changeTracker, file, getAccessor, declaration, container); if (isReadonly) { // readonly modifier only existed in classLikeDeclaration var constructor = ts.getFirstConstructorWithBody(container); if (constructor) { updateReadonlyPropertyInitializerStatementConstructor(changeTracker, file, constructor, fieldName.text, originalName); } } else { var setAccessor = generateSetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); ts.suppressLeadingAndTrailingTrivia(setAccessor); insertAccessor(changeTracker, file, setAccessor, declaration, container); } return changeTracker.getChanges(); } codefix.generateAccessorFromProperty = generateAccessorFromProperty; function isConvertibleName(name) { return ts.isIdentifier(name) || ts.isStringLiteral(name); } function isAcceptedDeclaration(node) { return ts.isParameterPropertyDeclaration(node, node.parent) || ts.isPropertyDeclaration(node) || ts.isPropertyAssignment(node); } function createPropertyName(name, originalName) { return ts.isIdentifier(originalName) ? ts.factory.createIdentifier(name) : ts.factory.createStringLiteral(name); } function createAccessorAccessExpression(fieldName, isStatic, container) { var leftHead = isStatic ? container.name : ts.factory.createThis(); // TODO: GH#18217 return ts.isIdentifier(fieldName) ? ts.factory.createPropertyAccessExpression(leftHead, fieldName) : ts.factory.createElementAccessExpression(leftHead, ts.factory.createStringLiteralFromNode(fieldName)); } function prepareModifierFlagsForAccessor(modifierFlags) { modifierFlags &= ~64 /* ModifierFlags.Readonly */; // avoid Readonly modifier because it will convert to get accessor modifierFlags &= ~8 /* ModifierFlags.Private */; if (!(modifierFlags & 16 /* ModifierFlags.Protected */)) { modifierFlags |= 4 /* ModifierFlags.Public */; } return modifierFlags; } function prepareModifierFlagsForField(modifierFlags) { modifierFlags &= ~4 /* ModifierFlags.Public */; modifierFlags &= ~16 /* ModifierFlags.Protected */; modifierFlags |= 8 /* ModifierFlags.Private */; return modifierFlags; } function getAccessorConvertiblePropertyAtPosition(file, program, start, end, considerEmptySpans) { if (considerEmptySpans === void 0) { considerEmptySpans = true; } var node = ts.getTokenAtPosition(file, start); var cursorRequest = start === end && considerEmptySpans; var declaration = ts.findAncestor(node.parent, isAcceptedDeclaration); // make sure declaration have AccessibilityModifier or Static Modifier or Readonly Modifier var meaning = 28 /* ModifierFlags.AccessibilityModifier */ | 32 /* ModifierFlags.Static */ | 64 /* ModifierFlags.Readonly */; if (!declaration || (!(ts.nodeOverlapsWithStartEnd(declaration.name, file, start, end) || cursorRequest))) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_property_for_which_to_generate_accessor) }; } if (!isConvertibleName(declaration.name)) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Name_is_not_valid) }; } if ((ts.getEffectiveModifierFlags(declaration) | meaning) !== meaning) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Can_only_convert_property_with_modifier) }; } var name = declaration.name.text; var startWithUnderscore = ts.startsWithUnderscore(name); var fieldName = createPropertyName(startWithUnderscore ? name : ts.getUniqueName("_".concat(name), file), declaration.name); var accessorName = createPropertyName(startWithUnderscore ? ts.getUniqueName(name.substring(1), file) : name, declaration.name); return { isStatic: ts.hasStaticModifier(declaration), isReadonly: ts.hasEffectiveReadonlyModifier(declaration), type: getDeclarationType(declaration, program), container: declaration.kind === 164 /* SyntaxKind.Parameter */ ? declaration.parent.parent : declaration.parent, originalName: declaration.name.text, declaration: declaration, fieldName: fieldName, accessorName: accessorName, renameAccessor: startWithUnderscore }; } codefix.getAccessorConvertiblePropertyAtPosition = getAccessorConvertiblePropertyAtPosition; function generateGetAccessor(fieldName, accessorName, type, modifiers, isStatic, container) { return ts.factory.createGetAccessorDeclaration( /*decorators*/ undefined, modifiers, accessorName, /*parameters*/ undefined, // TODO: GH#18217 type, ts.factory.createBlock([ ts.factory.createReturnStatement(createAccessorAccessExpression(fieldName, isStatic, container)) ], /*multiLine*/ true)); } function generateSetAccessor(fieldName, accessorName, type, modifiers, isStatic, container) { return ts.factory.createSetAccessorDeclaration( /*decorators*/ undefined, modifiers, accessorName, [ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, ts.factory.createIdentifier("value"), /*questionToken*/ undefined, type)], ts.factory.createBlock([ ts.factory.createExpressionStatement(ts.factory.createAssignment(createAccessorAccessExpression(fieldName, isStatic, container), ts.factory.createIdentifier("value"))) ], /*multiLine*/ true)); } function updatePropertyDeclaration(changeTracker, file, declaration, type, fieldName, modifiers) { var property = ts.factory.updatePropertyDeclaration(declaration, declaration.decorators, modifiers, fieldName, declaration.questionToken || declaration.exclamationToken, type, declaration.initializer); changeTracker.replaceNode(file, declaration, property); } function updatePropertyAssignmentDeclaration(changeTracker, file, declaration, fieldName) { var assignment = ts.factory.updatePropertyAssignment(declaration, fieldName, declaration.initializer); changeTracker.replacePropertyAssignment(file, declaration, assignment); } function updateFieldDeclaration(changeTracker, file, declaration, type, fieldName, modifiers) { if (ts.isPropertyDeclaration(declaration)) { updatePropertyDeclaration(changeTracker, file, declaration, type, fieldName, modifiers); } else if (ts.isPropertyAssignment(declaration)) { updatePropertyAssignmentDeclaration(changeTracker, file, declaration, fieldName); } else { changeTracker.replaceNode(file, declaration, ts.factory.updateParameterDeclaration(declaration, declaration.decorators, modifiers, declaration.dotDotDotToken, ts.cast(fieldName, ts.isIdentifier), declaration.questionToken, declaration.type, declaration.initializer)); } } function insertAccessor(changeTracker, file, accessor, declaration, container) { ts.isParameterPropertyDeclaration(declaration, declaration.parent) ? changeTracker.insertMemberAtStart(file, container, accessor) : ts.isPropertyAssignment(declaration) ? changeTracker.insertNodeAfterComma(file, declaration, accessor) : changeTracker.insertNodeAfter(file, declaration, accessor); } function updateReadonlyPropertyInitializerStatementConstructor(changeTracker, file, constructor, fieldName, originalName) { if (!constructor.body) return; constructor.body.forEachChild(function recur(node) { if (ts.isElementAccessExpression(node) && node.expression.kind === 108 /* SyntaxKind.ThisKeyword */ && ts.isStringLiteral(node.argumentExpression) && node.argumentExpression.text === originalName && ts.isWriteAccess(node)) { changeTracker.replaceNode(file, node.argumentExpression, ts.factory.createStringLiteral(fieldName)); } if (ts.isPropertyAccessExpression(node) && node.expression.kind === 108 /* SyntaxKind.ThisKeyword */ && node.name.text === originalName && ts.isWriteAccess(node)) { changeTracker.replaceNode(file, node.name, ts.factory.createIdentifier(fieldName)); } if (!ts.isFunctionLike(node) && !ts.isClassLike(node)) { node.forEachChild(recur); } }); } function getDeclarationType(declaration, program) { var typeNode = ts.getTypeAnnotationNode(declaration); if (ts.isPropertyDeclaration(declaration) && typeNode && declaration.questionToken) { var typeChecker = program.getTypeChecker(); var type = typeChecker.getTypeFromTypeNode(typeNode); if (!typeChecker.isTypeAssignableTo(typeChecker.getUndefinedType(), type)) { var types = ts.isUnionTypeNode(typeNode) ? typeNode.types : [typeNode]; return ts.factory.createUnionTypeNode(__spreadArray(__spreadArray([], types, true), [ts.factory.createKeywordTypeNode(153 /* SyntaxKind.UndefinedKeyword */)], false)); } } return typeNode; } function getAllSupers(decl, checker) { var res = []; while (decl) { var superElement = ts.getClassExtendsHeritageElement(decl); var superSymbol = superElement && checker.getSymbolAtLocation(superElement.expression); if (!superSymbol) break; var symbol = superSymbol.flags & 2097152 /* SymbolFlags.Alias */ ? checker.getAliasedSymbol(superSymbol) : superSymbol; var superDecl = symbol.declarations && ts.find(symbol.declarations, ts.isClassLike); if (!superDecl) break; res.push(superDecl); decl = superDecl; } return res; } codefix.getAllSupers = getAllSupers; })(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.factory.createImportEqualsDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, namespace.name, ts.factory.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 ? 208 /* SyntaxKind.CallExpression */ : 209 /* SyntaxKind.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_2_index_type_3.code, ts.Diagnostics._0_index_type_1_is_not_assignable_to_2_index_type_3.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_2 = context.sourceFile; var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile_2, expr, ts.factory.createPropertyAccessExpression(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 getCodeActionsForStrictClassInitializationErrors(context) { var info = getInfo(context.sourceFile, context.span.start); if (!info) return; var result = []; ts.append(result, getActionForAddMissingUndefinedType(context, info)); ts.append(result, getActionForAddMissingDefiniteAssignmentAssertion(context, info)); ts.append(result, getActionForAddMissingInitializer(context, info)); return result; }, fixIds: [fixIdAddDefiniteAssignmentAssertions, fixIdAddUndefinedType, fixIdAddInitializer], getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var info = getInfo(diag.file, diag.start); if (!info) return; switch (context.fixId) { case fixIdAddDefiniteAssignmentAssertions: addDefiniteAssignmentAssertion(changes, diag.file, info.prop); break; case fixIdAddUndefinedType: addUndefinedType(changes, diag.file, info); break; case fixIdAddInitializer: var checker = context.program.getTypeChecker(); var initializer = getInitializer(checker, info.prop); if (!initializer) return; addInitializer(changes, diag.file, info.prop, initializer); break; default: ts.Debug.fail(JSON.stringify(context.fixId)); } }); }, }); function getInfo(sourceFile, pos) { var token = ts.getTokenAtPosition(sourceFile, pos); if (ts.isIdentifier(token) && ts.isPropertyDeclaration(token.parent)) { var type = ts.getEffectiveTypeAnnotationNode(token.parent); if (type) { return { type: type, prop: token.parent, isJs: ts.isInJSFile(token.parent) }; } } return undefined; } function getActionForAddMissingDefiniteAssignmentAssertion(context, info) { if (info.isJs) return undefined; var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addDefiniteAssignmentAssertion(t, context.sourceFile, info.prop); }); return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_definite_assignment_assertion_to_property_0, info.prop.getText()], fixIdAddDefiniteAssignmentAssertions, ts.Diagnostics.Add_definite_assignment_assertions_to_all_uninitialized_properties); } function addDefiniteAssignmentAssertion(changeTracker, propertyDeclarationSourceFile, propertyDeclaration) { ts.suppressLeadingAndTrailingTrivia(propertyDeclaration); var property = ts.factory.updatePropertyDeclaration(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, ts.factory.createToken(53 /* SyntaxKind.ExclamationToken */), propertyDeclaration.type, propertyDeclaration.initializer); changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property); } function getActionForAddMissingUndefinedType(context, info) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addUndefinedType(t, context.sourceFile, info); }); return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_undefined_type_to_property_0, info.prop.name.getText()], fixIdAddUndefinedType, ts.Diagnostics.Add_undefined_type_to_all_uninitialized_properties); } function addUndefinedType(changeTracker, sourceFile, info) { var undefinedTypeNode = ts.factory.createKeywordTypeNode(153 /* SyntaxKind.UndefinedKeyword */); var types = ts.isUnionTypeNode(info.type) ? info.type.types.concat(undefinedTypeNode) : [info.type, undefinedTypeNode]; var unionTypeNode = ts.factory.createUnionTypeNode(types); if (info.isJs) { changeTracker.addJSDocTags(sourceFile, info.prop, [ts.factory.createJSDocTypeTag(/*tagName*/ undefined, ts.factory.createJSDocTypeExpression(unionTypeNode))]); } else { changeTracker.replaceNode(sourceFile, info.type, unionTypeNode); } } function getActionForAddMissingInitializer(context, info) { if (info.isJs) return undefined; var checker = context.program.getTypeChecker(); var initializer = getInitializer(checker, info.prop); if (!initializer) return undefined; var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addInitializer(t, context.sourceFile, info.prop, initializer); }); return codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Add_initializer_to_property_0, info.prop.name.getText()], fixIdAddInitializer, ts.Diagnostics.Add_initializers_to_all_uninitialized_properties); } function addInitializer(changeTracker, propertyDeclarationSourceFile, propertyDeclaration, initializer) { ts.suppressLeadingAndTrailingTrivia(propertyDeclaration); var property = ts.factory.updatePropertyDeclaration(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 /* TypeFlags.BooleanLiteral */) { return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? ts.factory.createFalse() : ts.factory.createTrue(); } else if (type.isStringLiteral()) { return ts.factory.createStringLiteral(type.value); } else if (type.isNumberLiteral()) { return ts.factory.createNumericLiteral(type.value); } else if (type.flags & 2048 /* TypeFlags.BigIntLiteral */) { return ts.factory.createBigIntLiteral(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.hasSyntacticModifier(classDeclaration, 128 /* ModifierFlags.Abstract */)) return undefined; var constructorDeclaration = ts.getFirstConstructorWithBody(classDeclaration); if (constructorDeclaration && constructorDeclaration.parameters.length) return undefined; return ts.factory.createNewExpression(ts.factory.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined); } else if (checker.isArrayLikeType(type)) { return ts.factory.createArrayLiteralExpression(); } 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 info = getInfo(context.sourceFile, context.program, context.span.start); if (!info) { return undefined; } var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, info); }); 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) { var info = getInfo(diag.file, context.program, diag.start); if (info) { doChange(changes, context.sourceFile, info); } }); }, }); function doChange(changes, sourceFile, info) { var allowSyntheticDefaults = info.allowSyntheticDefaults, defaultImportName = info.defaultImportName, namedImports = info.namedImports, statement = info.statement, required = info.required; changes.replaceNode(sourceFile, statement, defaultImportName && !allowSyntheticDefaults ? ts.factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, defaultImportName, ts.factory.createExternalModuleReference(required)) : ts.factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, namedImports), required, /*assertClause*/ undefined)); } function getInfo(sourceFile, program, 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); var defaultImportName = ts.tryCast(decl.name, ts.isIdentifier); var namedImports = ts.isObjectBindingPattern(decl.name) ? tryCreateNamedImportsFromObjectBindingPattern(decl.name) : undefined; if (defaultImportName || namedImports) { return { allowSyntheticDefaults: ts.getAllowSyntheticDefaultImports(program.getCompilerOptions()), defaultImportName: defaultImportName, namedImports: namedImports, statement: ts.cast(decl.parent.parent, ts.isVariableStatement), required: ts.first(parent.arguments) }; } } function tryCreateNamedImportsFromObjectBindingPattern(node) { var importSpecifiers = []; for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { var element = _a[_i]; if (!ts.isIdentifier(element.name) || element.initializer) { return undefined; } importSpecifiers.push(ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.tryCast(element.propertyName, ts.isIdentifier), element.name)); } if (importSpecifiers.length) { return ts.factory.createNamedImports(importSpecifiers); } } })(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 getCodeActionsToUseBigintLiteral(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.factory.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 getCodeActionsToAddMissingTypeof(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 === 100 /* SyntaxKind.ImportKeyword */, "This token should be an ImportKeyword"); ts.Debug.assert(token.parent.kind === 200 /* SyntaxKind.ImportType */, "Token parent should be an ImportType"); return token.parent; } function doChange(changes, sourceFile, importType) { var newTypeNode = ts.factory.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 fixID = "wrapJsxInFragment"; var errorCodes = [ts.Diagnostics.JSX_expressions_must_have_one_parent_element.code]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function getCodeActionsToWrapJsxInFragment(context) { var sourceFile = context.sourceFile, span = context.span; var node = findNodeToFix(sourceFile, span.start); if (!node) return undefined; var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, node); }); return [codefix.createCodeFixAction(fixID, changes, ts.Diagnostics.Wrap_in_JSX_fragment, fixID, ts.Diagnostics.Wrap_all_unparented_JSX_in_JSX_fragment)]; }, fixIds: [fixID], getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var node = findNodeToFix(context.sourceFile, diag.start); if (!node) return undefined; doChange(changes, context.sourceFile, node); }); }, }); function findNodeToFix(sourceFile, pos) { // The error always at 1st token that is "<" in "" var lessThanToken = ts.getTokenAtPosition(sourceFile, pos); var firstJsxElementOrOpenElement = lessThanToken.parent; var binaryExpr = firstJsxElementOrOpenElement.parent; if (!ts.isBinaryExpression(binaryExpr)) { // In case the start element is a JsxSelfClosingElement, it the end. // For JsxOpenElement, find one more parent binaryExpr = binaryExpr.parent; if (!ts.isBinaryExpression(binaryExpr)) return undefined; } if (!ts.nodeIsMissing(binaryExpr.operatorToken)) return undefined; return binaryExpr; } function doChange(changeTracker, sf, node) { var jsx = flattenInvalidBinaryExpr(node); if (jsx) changeTracker.replaceNode(sf, node, ts.factory.createJsxFragment(ts.factory.createJsxOpeningFragment(), jsx, ts.factory.createJsxJsxClosingFragment())); } // The invalid syntax is constructed as // InvalidJsxTree :: One of // JsxElement CommaToken InvalidJsxTree // JsxElement CommaToken JsxElement function flattenInvalidBinaryExpr(node) { var children = []; var current = node; while (true) { if (ts.isBinaryExpression(current) && ts.nodeIsMissing(current.operatorToken) && current.operatorToken.kind === 27 /* SyntaxKind.CommaToken */) { children.push(current.left); if (ts.isJsxChild(current.right)) { children.push(current.right); // Indicates the tree has go to the bottom return children; } else if (ts.isBinaryExpression(current.right)) { current = current.right; continue; } // Unreachable case else return undefined; } // Unreachable case else return undefined; } } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixId = "fixConvertToMappedObjectType"; var errorCodes = [ts.Diagnostics.An_index_signature_parameter_type_cannot_be_a_literal_type_or_generic_type_Consider_using_a_mapped_object_type_instead.code]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function getCodeActionsToConvertToMappedTypeObject(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.tryCast(token.parent.parent, ts.isIndexSignatureDeclaration); if (!indexSignature) return undefined; var container = ts.isInterfaceDeclaration(indexSignature.parent) ? indexSignature.parent : ts.tryCast(indexSignature.parent.parent, ts.isTypeAliasDeclaration); if (!container) return undefined; return { indexSignature: indexSignature, container: container }; } function createTypeAliasFromInterface(declaration, type) { return ts.factory.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.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, ts.cast(parameter.name, ts.isIdentifier), parameter.type); var mappedIntersectionType = ts.factory.createMappedTypeNode(ts.hasEffectiveReadonlyModifier(indexSignature) ? ts.factory.createModifier(145 /* SyntaxKind.ReadonlyKeyword */) : undefined, mappedTypeParameter, /*nameType*/ undefined, indexSignature.questionToken, indexSignature.type, /*members*/ undefined); var intersectionType = ts.factory.createIntersectionTypeNode(__spreadArray(__spreadArray(__spreadArray([], ts.getAllSuperTypeNodes(container), true), [ mappedIntersectionType ], false), (otherMembers.length ? [ts.factory.createTypeLiteralNode(otherMembers)] : ts.emptyArray), true)); 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 = "removeAccidentalCallParentheses"; var errorCodes = [ ts.Diagnostics.This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var callExpression = ts.findAncestor(ts.getTokenAtPosition(context.sourceFile, context.span.start), ts.isCallExpression); if (!callExpression) { return undefined; } var changes = ts.textChanges.ChangeTracker.with(context, function (t) { t.deleteRange(context.sourceFile, { pos: callExpression.expression.end, end: callExpression.end }); }); return [codefix.createCodeFixActionWithoutFixAll(fixId, changes, ts.Diagnostics.Remove_parentheses)]; }, fixIds: [fixId], }); })(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 getCodeActionsToRemoveUnnecessaryAwait(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 === 132 /* SyntaxKind.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 !== 103 /* SyntaxKind.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 getCodeActionsToSplitTypeOnlyImport(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.factory.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.factory.updateImportClause(importClause, importClause.isTypeOnly, importClause.name, /*namedBindings*/ undefined), importDeclaration.moduleSpecifier, importDeclaration.assertClause)); changes.insertNodeAfter(context.sourceFile, importDeclaration, ts.factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.updateImportClause(importClause, importClause.isTypeOnly, /*name*/ undefined, importClause.namedBindings), importDeclaration.moduleSpecifier, importDeclaration.assertClause)); } })(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 getCodeActionsToConvertConstToLet(context) { var sourceFile = context.sourceFile, span = context.span, program = context.program; var range = getConstTokenRange(sourceFile, span.start, program); if (range === undefined) return; var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, range); }); return [codefix.createCodeFixAction(fixId, changes, ts.Diagnostics.Convert_const_to_let, fixId, ts.Diagnostics.Convert_const_to_let)]; }, fixIds: [fixId] }); function getConstTokenRange(sourceFile, pos, program) { var _a; var checker = program.getTypeChecker(); var symbol = checker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, pos)); var declaration = ts.tryCast((_a = symbol === null || symbol === void 0 ? void 0 : symbol.valueDeclaration) === null || _a === void 0 ? void 0 : _a.parent, ts.isVariableDeclarationList); if (declaration === undefined) return; var constToken = ts.findChildOfKind(declaration, 85 /* SyntaxKind.ConstKeyword */, sourceFile); if (constToken === undefined) return; return ts.createRange(constToken.pos, constToken.end); } function doChange(changes, sourceFile, range) { changes.replaceRangeWithText(sourceFile, range, "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 /* SyntaxKind.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.factory.createToken(27 /* SyntaxKind.CommaToken */); changes.replaceNode(sourceFile, node, newNode); } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var codefix; (function (codefix) { var fixName = "addVoidToPromise"; var fixId = "addVoidToPromise"; var errorCodes = [ ts.Diagnostics.Expected_1_argument_but_got_0_new_Promise_needs_a_JSDoc_hint_to_produce_a_resolve_that_can_be_called_without_arguments.code, ts.Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise.code ]; codefix.registerCodeFix({ errorCodes: errorCodes, fixIds: [fixId], getCodeActions: function (context) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span, context.program); }); if (changes.length > 0) { return [codefix.createCodeFixAction(fixName, changes, ts.Diagnostics.Add_void_to_Promise_resolved_without_a_value, fixId, ts.Diagnostics.Add_void_to_all_Promises_resolved_without_a_value)]; } }, getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag, context.program, new ts.Set()); }); } }); function makeChange(changes, sourceFile, span, program, seen) { var node = ts.getTokenAtPosition(sourceFile, span.start); if (!ts.isIdentifier(node) || !ts.isCallExpression(node.parent) || node.parent.expression !== node || node.parent.arguments.length !== 0) return; var checker = program.getTypeChecker(); var symbol = checker.getSymbolAtLocation(node); // decl should be `new Promise(() => {})` var decl = symbol === null || symbol === void 0 ? void 0 : symbol.valueDeclaration; if (!decl || !ts.isParameter(decl) || !ts.isNewExpression(decl.parent.parent)) return; // no need to make this change if we have already seen this parameter. if (seen === null || seen === void 0 ? void 0 : seen.has(decl)) return; seen === null || seen === void 0 ? void 0 : seen.add(decl); var typeArguments = getEffectiveTypeArguments(decl.parent.parent); if (ts.some(typeArguments)) { // append ` | void` to type argument var typeArgument = typeArguments[0]; var needsParens = !ts.isUnionTypeNode(typeArgument) && !ts.isParenthesizedTypeNode(typeArgument) && ts.isParenthesizedTypeNode(ts.factory.createUnionTypeNode([typeArgument, ts.factory.createKeywordTypeNode(114 /* SyntaxKind.VoidKeyword */)]).types[0]); if (needsParens) { changes.insertText(sourceFile, typeArgument.pos, "("); } changes.insertText(sourceFile, typeArgument.end, needsParens ? ") | void" : " | void"); } else { // make sure the Promise is type is untyped (i.e., `unknown`) var signature = checker.getResolvedSignature(node.parent); var parameter = signature === null || signature === void 0 ? void 0 : signature.parameters[0]; var parameterType = parameter && checker.getTypeOfSymbolAtLocation(parameter, decl.parent.parent); if (ts.isInJSFile(decl)) { if (!parameterType || parameterType.flags & 3 /* TypeFlags.AnyOrUnknown */) { // give the expression a type changes.insertText(sourceFile, decl.parent.parent.end, ")"); changes.insertText(sourceFile, ts.skipTrivia(sourceFile.text, decl.parent.parent.pos), "/** @type {Promise} */("); } } else { if (!parameterType || parameterType.flags & 2 /* TypeFlags.Unknown */) { // add `void` type argument changes.insertText(sourceFile, decl.parent.parent.expression.end, ""); } } } } function getEffectiveTypeArguments(node) { var _a; if (ts.isInJSFile(node)) { if (ts.isParenthesizedExpression(node.parent)) { var jsDocType = (_a = ts.getJSDocTypeTag(node.parent)) === null || _a === void 0 ? void 0 : _a.typeExpression.type; if (jsDocType && ts.isTypeReferenceNode(jsDocType) && ts.isIdentifier(jsDocType.typeName) && ts.idText(jsDocType.typeName) === "Promise") { return jsDocType.typeArguments; } } } else { return node.typeArguments; } } })(codefix = ts.codefix || (ts.codefix = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var refactorName = "Convert export"; var defaultToNamedAction = { name: "Convert default export to named export", description: ts.Diagnostics.Convert_default_export_to_named_export.message, kind: "refactor.rewrite.export.named" }; var namedToDefaultAction = { name: "Convert named export to default export", description: ts.Diagnostics.Convert_named_export_to_default_export.message, kind: "refactor.rewrite.export.default" }; refactor.registerRefactor(refactorName, { kinds: [ defaultToNamedAction.kind, namedToDefaultAction.kind ], getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndDefaultExports(context) { var info = getInfo(context, context.triggerReason === "invoked"); if (!info) return ts.emptyArray; if (!refactor.isRefactorErrorInfo(info)) { var action = info.wasDefault ? defaultToNamedAction : namedToDefaultAction; return [{ name: refactorName, description: action.description, actions: [action] }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [ { name: refactorName, description: ts.Diagnostics.Convert_default_export_to_named_export.message, actions: [ __assign(__assign({}, defaultToNamedAction), { notApplicableReason: info.error }), __assign(__assign({}, namedToDefaultAction), { notApplicableReason: info.error }), ] } ]; } return ts.emptyArray; }, getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndDefaultExports(context, actionName) { ts.Debug.assert(actionName === defaultToNamedAction.name || actionName === namedToDefaultAction.name, "Unexpected action name"); var info = getInfo(context); ts.Debug.assert(info && !refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(context.file, context.program, info, t, context.cancellationToken); }); return { edits: edits, renameFilename: undefined, renameLocation: undefined }; }, }); ; function getInfo(context, considerPartialSpans) { if (considerPartialSpans === void 0) { considerPartialSpans = true; } var file = context.file, program = context.program; var span = ts.getRefactorContextSpan(context); var token = ts.getTokenAtPosition(file, span.start); var exportNode = !!(token.parent && ts.getSyntacticModifierFlags(token.parent) & 1 /* ModifierFlags.Export */) && considerPartialSpans ? token.parent : ts.getParentNodeInSpan(token, file, span); if (!exportNode || (!ts.isSourceFile(exportNode.parent) && !(ts.isModuleBlock(exportNode.parent) && ts.isAmbientModule(exportNode.parent.parent)))) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_export_statement) }; } var exportingModuleSymbol = ts.isSourceFile(exportNode.parent) ? exportNode.parent.symbol : exportNode.parent.parent.symbol; var flags = ts.getSyntacticModifierFlags(exportNode) || ((ts.isExportAssignment(exportNode) && !exportNode.isExportEquals) ? 513 /* ModifierFlags.ExportDefault */ : 0 /* ModifierFlags.None */); var wasDefault = !!(flags & 512 /* ModifierFlags.Default */); // If source file already has a default export, don't offer refactor. if (!(flags & 1 /* ModifierFlags.Export */) || !wasDefault && exportingModuleSymbol.exports.has("default" /* InternalSymbolName.Default */)) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.This_file_already_has_a_default_export) }; } var checker = program.getTypeChecker(); var noSymbolError = function (id) { return (ts.isIdentifier(id) && checker.getSymbolAtLocation(id)) ? undefined : { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Can_only_convert_named_export) }; }; switch (exportNode.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: { var node = exportNode; if (!node.name) return undefined; return noSymbolError(node.name) || { exportNode: node, exportName: node.name, wasDefault: wasDefault, exportingModuleSymbol: exportingModuleSymbol }; } case 237 /* SyntaxKind.VariableStatement */: { var vs = exportNode; // Must be `export const x = something;`. if (!(vs.declarationList.flags & 2 /* NodeFlags.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 noSymbolError(decl.name) || { exportNode: vs, exportName: decl.name, wasDefault: wasDefault, exportingModuleSymbol: exportingModuleSymbol }; } case 271 /* SyntaxKind.ExportAssignment */: { var node = exportNode; if (node.isExportEquals) return undefined; return noSymbolError(node.expression) || { exportNode: node, exportName: node.expression, wasDefault: wasDefault, exportingModuleSymbol: exportingModuleSymbol }; } 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) { if (ts.isExportAssignment(exportNode) && !exportNode.isExportEquals) { var exp = exportNode.expression; var spec = makeExportSpecifier(exp.text, exp.text); changes.replaceNode(exportingSourceFile, exportNode, ts.factory.createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, ts.factory.createNamedExports([spec]))); } else { changes.delete(exportingSourceFile, ts.Debug.checkDefined(ts.findModifier(exportNode, 88 /* SyntaxKind.DefaultKeyword */), "Should find a default keyword in modifier list")); } } else { var exportKeyword = ts.Debug.checkDefined(ts.findModifier(exportNode, 93 /* SyntaxKind.ExportKeyword */), "Should find an export keyword in modifier list"); switch (exportNode.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: changes.insertNodeAfter(exportingSourceFile, exportKeyword, ts.factory.createToken(88 /* SyntaxKind.DefaultKeyword */)); break; case 237 /* SyntaxKind.VariableStatement */: // If 'x' isn't used in this file and doesn't have type definition, `export const x = 0;` --> `export default 0;` var decl = ts.first(exportNode.declarationList.declarations); if (!ts.FindAllReferences.Core.isSymbolReferencedInFile(exportName, checker, exportingSourceFile) && !decl.type) { // We checked in `getInfo` that an initializer exists. changes.replaceNode(exportingSourceFile, exportNode, ts.factory.createExportDefault(ts.Debug.checkDefined(decl.initializer, "Initializer was previously known to be present"))); break; } // falls through case 260 /* SyntaxKind.EnumDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: // `export type T = number;` -> `type T = number; export default T;` changes.deleteModifier(exportingSourceFile, exportKeyword); changes.insertNodeAfter(exportingSourceFile, exportNode, ts.factory.createExportDefault(ts.factory.createIdentifier(exportName.text))); break; default: ts.Debug.fail("Unexpected exportNode kind ".concat(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 206 /* SyntaxKind.PropertyAccessExpression */: // `a.default` --> `a.foo` changes.replaceNode(importingSourceFile, ref, ts.factory.createIdentifier(exportName)); break; case 270 /* SyntaxKind.ImportSpecifier */: case 275 /* SyntaxKind.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 267 /* SyntaxKind.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.factory.createNamedImports([spec])); } else if (namedBindings.kind === 268 /* SyntaxKind.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 /* QuotePreference.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; } case 200 /* SyntaxKind.ImportType */: var importTypeNode = parent; changes.replaceNode(importingSourceFile, parent, ts.factory.createImportTypeNode(importTypeNode.argument, ts.factory.createIdentifier(exportName), importTypeNode.typeArguments, importTypeNode.isTypeOf)); break; default: ts.Debug.failBadSyntaxKind(parent); } } function changeNamedToDefaultImport(importingSourceFile, ref, changes) { var parent = ref.parent; switch (parent.kind) { case 206 /* SyntaxKind.PropertyAccessExpression */: // `a.foo` --> `a.default` changes.replaceNode(importingSourceFile, ref, ts.factory.createIdentifier("default")); break; case 270 /* SyntaxKind.ImportSpecifier */: { // `import { foo } from "./a";` --> `import foo from "./a";` // `import { foo as bar } from "./a";` --> `import bar from "./a";` var defaultImport = ts.factory.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 275 /* SyntaxKind.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 ".concat(parent.kind)); } } function makeImportSpecifier(propertyName, name) { return ts.factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : ts.factory.createIdentifier(propertyName), ts.factory.createIdentifier(name)); } function makeExportSpecifier(propertyName, name) { return ts.factory.createExportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : ts.factory.createIdentifier(propertyName), ts.factory.createIdentifier(name)); } })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var _a; var refactorName = "Convert import"; var actions = (_a = {}, _a[0 /* ImportKind.Named */] = { name: "Convert namespace import to named imports", description: ts.Diagnostics.Convert_namespace_import_to_named_imports.message, kind: "refactor.rewrite.import.named", }, _a[2 /* ImportKind.Namespace */] = { name: "Convert named imports to namespace import", description: ts.Diagnostics.Convert_named_imports_to_namespace_import.message, kind: "refactor.rewrite.import.namespace", }, _a[1 /* ImportKind.Default */] = { name: "Convert named imports to default import", description: ts.Diagnostics.Convert_named_imports_to_default_import.message, kind: "refactor.rewrite.import.default", }, _a); refactor.registerRefactor(refactorName, { kinds: ts.getOwnValues(actions).map(function (a) { return a.kind; }), getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndNamespacedImports(context) { var info = getImportConversionInfo(context, context.triggerReason === "invoked"); if (!info) return ts.emptyArray; if (!refactor.isRefactorErrorInfo(info)) { var action = actions[info.convertTo]; return [{ name: refactorName, description: action.description, actions: [action] }]; } if (context.preferences.provideRefactorNotApplicableReason) { return ts.getOwnValues(actions).map(function (action) { return ({ name: refactorName, description: action.description, actions: [__assign(__assign({}, action), { notApplicableReason: info.error })] }); }); } return ts.emptyArray; }, getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndNamespacedImports(context, actionName) { ts.Debug.assert(ts.some(ts.getOwnValues(actions), function (action) { return action.name === actionName; }), "Unexpected action name"); var info = getImportConversionInfo(context); ts.Debug.assert(info && !refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(context.file, context.program, t, info); }); return { edits: edits, renameFilename: undefined, renameLocation: undefined }; } }); function getImportConversionInfo(context, considerPartialSpans) { if (considerPartialSpans === void 0) { considerPartialSpans = true; } var file = context.file; var span = ts.getRefactorContextSpan(context); var token = ts.getTokenAtPosition(file, span.start); var importDecl = considerPartialSpans ? ts.findAncestor(token, ts.isImportDeclaration) : ts.getParentNodeInSpan(token, file, span); if (!importDecl || !ts.isImportDeclaration(importDecl)) return { error: "Selection is not an import declaration." }; var end = span.start + span.length; var nextToken = ts.findNextToken(importDecl, importDecl.parent, file); if (nextToken && end > nextToken.getStart()) return undefined; var importClause = importDecl.importClause; if (!importClause) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_import_clause) }; } if (!importClause.namedBindings) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_namespace_import_or_named_imports) }; } if (importClause.namedBindings.kind === 268 /* SyntaxKind.NamespaceImport */) { return { convertTo: 0 /* ImportKind.Named */, import: importClause.namedBindings }; } var shouldUseDefault = getShouldUseDefault(context.program, importClause); return shouldUseDefault ? { convertTo: 1 /* ImportKind.Default */, import: importClause.namedBindings } : { convertTo: 2 /* ImportKind.Namespace */, import: importClause.namedBindings }; } function getShouldUseDefault(program, importClause) { return ts.getAllowSyntheticDefaultImports(program.getCompilerOptions()) && isExportEqualsModule(importClause.parent.moduleSpecifier, program.getTypeChecker()); } function doChange(sourceFile, program, changes, info) { var checker = program.getTypeChecker(); if (info.convertTo === 0 /* ImportKind.Named */) { doChangeNamespaceToNamed(sourceFile, checker, changes, info.import, ts.getAllowSyntheticDefaultImports(program.getCompilerOptions())); } else { doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, info.import, info.convertTo === 1 /* ImportKind.Default */); } } function doChangeNamespaceToNamed(sourceFile, checker, changes, toConvert, allowSyntheticDefaultImports) { var usedAsNamespaceOrDefault = false; var nodesToReplace = []; var conflictingNames = new ts.Map(); ts.FindAllReferences.Core.eachSymbolReferenceInFile(toConvert.name, checker, sourceFile, function (id) { if (!ts.isPropertyAccessOrQualifiedName(id.parent)) { usedAsNamespaceOrDefault = true; } else { var exportName = getRightOfPropertyAccessOrQualifiedName(id.parent).text; if (checker.resolveName(exportName, id, 67108863 /* SymbolFlags.All */, /*excludeGlobals*/ true)) { conflictingNames.set(exportName, true); } ts.Debug.assert(getLeftOfPropertyAccessOrQualifiedName(id.parent) === id, "Parent expression should match id"); nodesToReplace.push(id.parent); } }); // We may need to change `mod.x` to `_x` to avoid a name conflict. var exportNameToImportName = new ts.Map(); for (var _i = 0, nodesToReplace_1 = nodesToReplace; _i < nodesToReplace_1.length; _i++) { var propertyAccessOrQualifiedName = nodesToReplace_1[_i]; var exportName = getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName).text; var importName = exportNameToImportName.get(exportName); if (importName === undefined) { exportNameToImportName.set(exportName, importName = conflictingNames.has(exportName) ? ts.getUniqueName(exportName, sourceFile) : exportName); } changes.replaceNode(sourceFile, propertyAccessOrQualifiedName, ts.factory.createIdentifier(importName)); } var importSpecifiers = []; exportNameToImportName.forEach(function (name, propertyName) { importSpecifiers.push(ts.factory.createImportSpecifier(/*isTypeOnly*/ false, name === propertyName ? undefined : ts.factory.createIdentifier(propertyName), ts.factory.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.factory.createIdentifier(toConvert.name.text) : undefined, importSpecifiers)); } } function getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName) { return ts.isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.name : propertyAccessOrQualifiedName.right; } function getLeftOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName) { return ts.isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.expression : propertyAccessOrQualifiedName.left; } function doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, toConvert, shouldUseDefault) { if (shouldUseDefault === void 0) { shouldUseDefault = getShouldUseDefault(program, toConvert.parent); } var checker = program.getTypeChecker(); var importDecl = toConvert.parent.parent; var moduleSpecifier = importDecl.moduleSpecifier; var toConvertSymbols = new ts.Set(); toConvert.elements.forEach(function (namedImport) { var symbol = checker.getSymbolAtLocation(namedImport.name); if (symbol) { toConvertSymbols.add(symbol); } }); var preferredName = moduleSpecifier && ts.isStringLiteral(moduleSpecifier) ? ts.codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, 99 /* ScriptTarget.ESNext */) : "module"; function hasNamespaceNameConflict(namedImport) { // We need to check if the preferred namespace name (`preferredName`) we'd like to use in the refactored code will present a name conflict. // A name conflict means that, in a scope where we would like to use the preferred namespace name, there already exists a symbol with that name in that scope. // We are going to use the namespace name in the scopes the named imports being refactored are referenced, // so we look for conflicts by looking at every reference to those named imports. return !!ts.FindAllReferences.Core.eachSymbolReferenceInFile(namedImport.name, checker, sourceFile, function (id) { var symbol = checker.resolveName(preferredName, id, 67108863 /* SymbolFlags.All */, /*excludeGlobals*/ true); if (symbol) { // There already is a symbol with the same name as the preferred namespace name. if (toConvertSymbols.has(symbol)) { // `preferredName` resolves to a symbol for one of the named import references we are going to transform into namespace import references... return ts.isExportSpecifier(id.parent); // ...but if this reference is an export specifier, it will not be transformed, so it is a conflict; otherwise, it will be renamed and is not a conflict. } return true; // `preferredName` resolves to any other symbol, which will be present in the refactored code and so poses a name conflict. } return false; // There is no symbol with the same name as the preferred namespace name, so no conflict. }); } var namespaceNameConflicts = toConvert.elements.some(hasNamespaceNameConflict); var namespaceImportName = namespaceNameConflicts ? ts.getUniqueName(preferredName, sourceFile) : preferredName; // Imports that need to be kept as named imports in the refactored code, to avoid changing the semantics. // More specifically, those are named imports that appear in named exports in the original code, e.g. `a` in `import { a } from "m"; export { a }`. var neededNamedImports = new ts.Set(); var _loop_17 = function (element) { var propertyName = (element.propertyName || element.name).text; ts.FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, function (id) { var access = ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(namespaceImportName), propertyName); if (ts.isShorthandPropertyAssignment(id.parent)) { changes.replaceNode(sourceFile, id.parent, ts.factory.createPropertyAssignment(id.text, access)); } else if (ts.isExportSpecifier(id.parent)) { neededNamedImports.add(element); } else { changes.replaceNode(sourceFile, id, access); } }); }; for (var _i = 0, _a = toConvert.elements; _i < _a.length; _i++) { var element = _a[_i]; _loop_17(element); } changes.replaceNode(sourceFile, toConvert, shouldUseDefault ? ts.factory.createIdentifier(namespaceImportName) : ts.factory.createNamespaceImport(ts.factory.createIdentifier(namespaceImportName))); if (neededNamedImports.size) { var newNamedImports = ts.arrayFrom(neededNamedImports.values()).map(function (element) { return ts.factory.createImportSpecifier(element.isTypeOnly, element.propertyName && ts.factory.createIdentifier(element.propertyName.text), ts.factory.createIdentifier(element.name.text)); }); changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, newNamedImports)); } } refactor.doChangeNamedToNamespaceOrDefault = doChangeNamedToNamespaceOrDefault; function isExportEqualsModule(moduleSpecifier, checker) { var externalModule = checker.resolveExternalModuleName(moduleSpecifier); if (!externalModule) return false; var exportEquals = checker.resolveExternalModuleSymbol(externalModule); return externalModule !== exportEquals; } function updateImport(old, defaultImportName, elements) { return ts.factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, elements && elements.length ? ts.factory.createNamedImports(elements) : undefined), old.moduleSpecifier, /*assertClause*/ undefined); } })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var convertToOptionalChainExpression; (function (convertToOptionalChainExpression) { var refactorName = "Convert to optional chain expression"; var convertToOptionalChainExpressionMessage = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_optional_chain_expression); var toOptionalChainAction = { name: refactorName, description: convertToOptionalChainExpressionMessage, kind: "refactor.rewrite.expression.optionalChain", }; refactor.registerRefactor(refactorName, { kinds: [toOptionalChainAction.kind], getEditsForAction: getRefactorEditsToConvertToOptionalChain, getAvailableActions: getRefactorActionsToConvertToOptionalChain, }); function getRefactorActionsToConvertToOptionalChain(context) { var info = getInfo(context, context.triggerReason === "invoked"); if (!info) return ts.emptyArray; if (!refactor.isRefactorErrorInfo(info)) { return [{ name: refactorName, description: convertToOptionalChainExpressionMessage, actions: [toOptionalChainAction], }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [{ name: refactorName, description: convertToOptionalChainExpressionMessage, actions: [__assign(__assign({}, toOptionalChainAction), { notApplicableReason: info.error })], }]; } return ts.emptyArray; } function getRefactorEditsToConvertToOptionalChain(context, actionName) { var info = getInfo(context); ts.Debug.assert(info && !refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(context.file, context.program.getTypeChecker(), t, info, actionName); }); return { edits: edits, renameFilename: undefined, renameLocation: undefined }; } ; function isValidExpression(node) { return ts.isBinaryExpression(node) || ts.isConditionalExpression(node); } function isValidStatement(node) { return ts.isExpressionStatement(node) || ts.isReturnStatement(node) || ts.isVariableStatement(node); } function isValidExpressionOrStatement(node) { return isValidExpression(node) || isValidStatement(node); } function getInfo(context, considerEmptySpans) { if (considerEmptySpans === void 0) { considerEmptySpans = true; } var file = context.file, program = context.program; var span = ts.getRefactorContextSpan(context); var forEmptySpan = span.length === 0; if (forEmptySpan && !considerEmptySpans) return undefined; // selecting fo[|o && foo.ba|]r should be valid, so adjust span to fit start and end tokens var startToken = ts.getTokenAtPosition(file, span.start); var endToken = ts.findTokenOnLeftOfPosition(file, span.start + span.length); var adjustedSpan = ts.createTextSpanFromBounds(startToken.pos, endToken && endToken.end >= startToken.pos ? endToken.getEnd() : startToken.getEnd()); var parent = forEmptySpan ? getValidParentNodeOfEmptySpan(startToken) : getValidParentNodeContainingSpan(startToken, adjustedSpan); var expression = parent && isValidExpressionOrStatement(parent) ? getExpression(parent) : undefined; if (!expression) return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_convertible_access_expression) }; var checker = program.getTypeChecker(); return ts.isConditionalExpression(expression) ? getConditionalInfo(expression, checker) : getBinaryInfo(expression); } function getConditionalInfo(expression, checker) { var condition = expression.condition; var finalExpression = getFinalExpressionInChain(expression.whenTrue); if (!finalExpression || checker.isNullableType(checker.getTypeAtLocation(finalExpression))) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_convertible_access_expression) }; } if ((ts.isPropertyAccessExpression(condition) || ts.isIdentifier(condition)) && getMatchingStart(condition, finalExpression.expression)) { return { finalExpression: finalExpression, occurrences: [condition], expression: expression }; } else if (ts.isBinaryExpression(condition)) { var occurrences = getOccurrencesInExpression(finalExpression.expression, condition); return occurrences ? { finalExpression: finalExpression, occurrences: occurrences, expression: expression } : { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_matching_access_expressions) }; } } function getBinaryInfo(expression) { if (expression.operatorToken.kind !== 55 /* SyntaxKind.AmpersandAmpersandToken */) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Can_only_convert_logical_AND_access_chains) }; } ; var finalExpression = getFinalExpressionInChain(expression.right); if (!finalExpression) return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_convertible_access_expression) }; var occurrences = getOccurrencesInExpression(finalExpression.expression, expression.left); return occurrences ? { finalExpression: finalExpression, occurrences: occurrences, expression: expression } : { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_matching_access_expressions) }; } /** * Gets a list of property accesses that appear in matchTo and occur in sequence in expression. */ function getOccurrencesInExpression(matchTo, expression) { var occurrences = []; while (ts.isBinaryExpression(expression) && expression.operatorToken.kind === 55 /* SyntaxKind.AmpersandAmpersandToken */) { var match = getMatchingStart(ts.skipParentheses(matchTo), ts.skipParentheses(expression.right)); if (!match) { break; } occurrences.push(match); matchTo = match; expression = expression.left; } var finalMatch = getMatchingStart(matchTo, expression); if (finalMatch) { occurrences.push(finalMatch); } return occurrences.length > 0 ? occurrences : undefined; } /** * Returns subchain if chain begins with subchain syntactically. */ function getMatchingStart(chain, subchain) { if (!ts.isIdentifier(subchain) && !ts.isPropertyAccessExpression(subchain) && !ts.isElementAccessExpression(subchain)) { return undefined; } return chainStartsWith(chain, subchain) ? subchain : undefined; } /** * Returns true if chain begins with subchain syntactically. */ function chainStartsWith(chain, subchain) { // skip until we find a matching identifier. while (ts.isCallExpression(chain) || ts.isPropertyAccessExpression(chain) || ts.isElementAccessExpression(chain)) { if (getTextOfChainNode(chain) === getTextOfChainNode(subchain)) break; chain = chain.expression; } // check that the chains match at each access. Call chains in subchain are not valid. while ((ts.isPropertyAccessExpression(chain) && ts.isPropertyAccessExpression(subchain)) || (ts.isElementAccessExpression(chain) && ts.isElementAccessExpression(subchain))) { if (getTextOfChainNode(chain) !== getTextOfChainNode(subchain)) return false; chain = chain.expression; subchain = subchain.expression; } // check if we have reached a final identifier. return ts.isIdentifier(chain) && ts.isIdentifier(subchain) && chain.getText() === subchain.getText(); } function getTextOfChainNode(node) { if (ts.isIdentifier(node) || ts.isStringOrNumericLiteralLike(node)) { return node.getText(); } if (ts.isPropertyAccessExpression(node)) { return getTextOfChainNode(node.name); } if (ts.isElementAccessExpression(node)) { return getTextOfChainNode(node.argumentExpression); } return undefined; } /** * Find the least ancestor of the input node that is a valid type for extraction and contains the input span. */ function getValidParentNodeContainingSpan(node, span) { while (node.parent) { if (isValidExpressionOrStatement(node) && span.length !== 0 && node.end >= span.start + span.length) { return node; } node = node.parent; } return undefined; } /** * Finds an ancestor of the input node that is a valid type for extraction, skipping subexpressions. */ function getValidParentNodeOfEmptySpan(node) { while (node.parent) { if (isValidExpressionOrStatement(node) && !isValidExpressionOrStatement(node.parent)) { return node; } node = node.parent; } return undefined; } /** * Gets an expression of valid extraction type from a valid statement or expression. */ function getExpression(node) { if (isValidExpression(node)) { return node; } if (ts.isVariableStatement(node)) { var variable = ts.getSingleVariableOfVariableStatement(node); var initializer = variable === null || variable === void 0 ? void 0 : variable.initializer; return initializer && isValidExpression(initializer) ? initializer : undefined; } return node.expression && isValidExpression(node.expression) ? node.expression : undefined; } /** * Gets a property access expression which may be nested inside of a binary expression. The final * expression in an && chain will occur as the right child of the parent binary expression, unless * it is followed by a different binary operator. * @param node the right child of a binary expression or a call expression. */ function getFinalExpressionInChain(node) { // foo && |foo.bar === 1|; - here the right child of the && binary expression is another binary expression. // the rightmost member of the && chain should be the leftmost child of that expression. node = ts.skipParentheses(node); if (ts.isBinaryExpression(node)) { return getFinalExpressionInChain(node.left); } // foo && |foo.bar()()| - nested calls are treated like further accesses. else if ((ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node) || ts.isCallExpression(node)) && !ts.isOptionalChain(node)) { return node; } return undefined; } /** * Creates an access chain from toConvert with '?.' accesses at expressions appearing in occurrences. */ function convertOccurrences(checker, toConvert, occurrences) { if (ts.isPropertyAccessExpression(toConvert) || ts.isElementAccessExpression(toConvert) || ts.isCallExpression(toConvert)) { var chain = convertOccurrences(checker, toConvert.expression, occurrences); var lastOccurrence = occurrences.length > 0 ? occurrences[occurrences.length - 1] : undefined; var isOccurrence = (lastOccurrence === null || lastOccurrence === void 0 ? void 0 : lastOccurrence.getText()) === toConvert.expression.getText(); if (isOccurrence) occurrences.pop(); if (ts.isCallExpression(toConvert)) { return isOccurrence ? ts.factory.createCallChain(chain, ts.factory.createToken(28 /* SyntaxKind.QuestionDotToken */), toConvert.typeArguments, toConvert.arguments) : ts.factory.createCallChain(chain, toConvert.questionDotToken, toConvert.typeArguments, toConvert.arguments); } else if (ts.isPropertyAccessExpression(toConvert)) { return isOccurrence ? ts.factory.createPropertyAccessChain(chain, ts.factory.createToken(28 /* SyntaxKind.QuestionDotToken */), toConvert.name) : ts.factory.createPropertyAccessChain(chain, toConvert.questionDotToken, toConvert.name); } else if (ts.isElementAccessExpression(toConvert)) { return isOccurrence ? ts.factory.createElementAccessChain(chain, ts.factory.createToken(28 /* SyntaxKind.QuestionDotToken */), toConvert.argumentExpression) : ts.factory.createElementAccessChain(chain, toConvert.questionDotToken, toConvert.argumentExpression); } } return toConvert; } function doChange(sourceFile, checker, changes, info, _actionName) { var finalExpression = info.finalExpression, occurrences = info.occurrences, expression = info.expression; var firstOccurrence = occurrences[occurrences.length - 1]; var convertedChain = convertOccurrences(checker, finalExpression, occurrences); if (convertedChain && (ts.isPropertyAccessExpression(convertedChain) || ts.isElementAccessExpression(convertedChain) || ts.isCallExpression(convertedChain))) { if (ts.isBinaryExpression(expression)) { changes.replaceNodeRange(sourceFile, firstOccurrence, finalExpression, convertedChain); } else if (ts.isConditionalExpression(expression)) { changes.replaceNode(sourceFile, expression, ts.factory.createBinaryExpression(convertedChain, ts.factory.createToken(60 /* SyntaxKind.QuestionQuestionToken */), expression.whenFalse)); } } } })(convertToOptionalChainExpression = refactor.convertToOptionalChainExpression || (refactor.convertToOptionalChainExpression = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var addOrRemoveBracesToArrowFunction; (function (addOrRemoveBracesToArrowFunction) { var refactorName = "Convert overload list to single signature"; var refactorDescription = ts.Diagnostics.Convert_overload_list_to_single_signature.message; var functionOverloadAction = { name: refactorName, description: refactorDescription, kind: "refactor.rewrite.function.overloadList", }; refactor.registerRefactor(refactorName, { kinds: [functionOverloadAction.kind], getEditsForAction: getRefactorEditsToConvertOverloadsToOneSignature, getAvailableActions: getRefactorActionsToConvertOverloadsToOneSignature }); function getRefactorActionsToConvertOverloadsToOneSignature(context) { var file = context.file, startPosition = context.startPosition, program = context.program; var info = getConvertableOverloadListAtPosition(file, startPosition, program); if (!info) return ts.emptyArray; return [{ name: refactorName, description: refactorDescription, actions: [functionOverloadAction] }]; } function getRefactorEditsToConvertOverloadsToOneSignature(context) { var file = context.file, startPosition = context.startPosition, program = context.program; var signatureDecls = getConvertableOverloadListAtPosition(file, startPosition, program); if (!signatureDecls) return undefined; var checker = program.getTypeChecker(); var lastDeclaration = signatureDecls[signatureDecls.length - 1]; var updated = lastDeclaration; switch (lastDeclaration.kind) { case 168 /* SyntaxKind.MethodSignature */: { updated = ts.factory.updateMethodSignature(lastDeclaration, lastDeclaration.modifiers, lastDeclaration.name, lastDeclaration.questionToken, lastDeclaration.typeParameters, getNewParametersForCombinedSignature(signatureDecls), lastDeclaration.type); break; } case 169 /* SyntaxKind.MethodDeclaration */: { updated = ts.factory.updateMethodDeclaration(lastDeclaration, lastDeclaration.decorators, lastDeclaration.modifiers, lastDeclaration.asteriskToken, lastDeclaration.name, lastDeclaration.questionToken, lastDeclaration.typeParameters, getNewParametersForCombinedSignature(signatureDecls), lastDeclaration.type, lastDeclaration.body); break; } case 174 /* SyntaxKind.CallSignature */: { updated = ts.factory.updateCallSignature(lastDeclaration, lastDeclaration.typeParameters, getNewParametersForCombinedSignature(signatureDecls), lastDeclaration.type); break; } case 171 /* SyntaxKind.Constructor */: { updated = ts.factory.updateConstructorDeclaration(lastDeclaration, lastDeclaration.decorators, lastDeclaration.modifiers, getNewParametersForCombinedSignature(signatureDecls), lastDeclaration.body); break; } case 175 /* SyntaxKind.ConstructSignature */: { updated = ts.factory.updateConstructSignature(lastDeclaration, lastDeclaration.typeParameters, getNewParametersForCombinedSignature(signatureDecls), lastDeclaration.type); break; } case 256 /* SyntaxKind.FunctionDeclaration */: { updated = ts.factory.updateFunctionDeclaration(lastDeclaration, lastDeclaration.decorators, lastDeclaration.modifiers, lastDeclaration.asteriskToken, lastDeclaration.name, lastDeclaration.typeParameters, getNewParametersForCombinedSignature(signatureDecls), lastDeclaration.type, lastDeclaration.body); break; } default: return ts.Debug.failBadSyntaxKind(lastDeclaration, "Unhandled signature kind in overload list conversion refactoring"); } if (updated === lastDeclaration) { return; // No edits to apply, do nothing } var edits = ts.textChanges.ChangeTracker.with(context, function (t) { t.replaceNodeRange(file, signatureDecls[0], signatureDecls[signatureDecls.length - 1], updated); }); return { renameFilename: undefined, renameLocation: undefined, edits: edits }; function getNewParametersForCombinedSignature(signatureDeclarations) { var lastSig = signatureDeclarations[signatureDeclarations.length - 1]; if (ts.isFunctionLikeDeclaration(lastSig) && lastSig.body) { // Trim away implementation signature arguments (they should already be compatible with overloads, but are likely less precise to guarantee compatability with the overloads) signatureDeclarations = signatureDeclarations.slice(0, signatureDeclarations.length - 1); } return ts.factory.createNodeArray([ ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createToken(25 /* SyntaxKind.DotDotDotToken */), "args", /*questionToken*/ undefined, ts.factory.createUnionTypeNode(ts.map(signatureDeclarations, convertSignatureParametersToTuple))) ]); } function convertSignatureParametersToTuple(decl) { var members = ts.map(decl.parameters, convertParameterToNamedTupleMember); return ts.setEmitFlags(ts.factory.createTupleTypeNode(members), ts.some(members, function (m) { return !!ts.length(ts.getSyntheticLeadingComments(m)); }) ? 0 /* EmitFlags.None */ : 1 /* EmitFlags.SingleLine */); } function convertParameterToNamedTupleMember(p) { ts.Debug.assert(ts.isIdentifier(p.name)); // This is checked during refactoring applicability checking var result = ts.setTextRange(ts.factory.createNamedTupleMember(p.dotDotDotToken, p.name, p.questionToken, p.type || ts.factory.createKeywordTypeNode(130 /* SyntaxKind.AnyKeyword */)), p); var parameterDocComment = p.symbol && p.symbol.getDocumentationComment(checker); if (parameterDocComment) { var newComment = ts.displayPartsToString(parameterDocComment); if (newComment.length) { ts.setSyntheticLeadingComments(result, [{ text: "*\n".concat(newComment.split("\n").map(function (c) { return " * ".concat(c); }).join("\n"), "\n "), kind: 3 /* SyntaxKind.MultiLineCommentTrivia */, pos: -1, end: -1, hasTrailingNewLine: true, hasLeadingNewline: true, }]); } } return result; } } function isConvertableSignatureDeclaration(d) { switch (d.kind) { case 168 /* SyntaxKind.MethodSignature */: case 169 /* SyntaxKind.MethodDeclaration */: case 174 /* SyntaxKind.CallSignature */: case 171 /* SyntaxKind.Constructor */: case 175 /* SyntaxKind.ConstructSignature */: case 256 /* SyntaxKind.FunctionDeclaration */: return true; } return false; } function getConvertableOverloadListAtPosition(file, startPosition, program) { var node = ts.getTokenAtPosition(file, startPosition); var containingDecl = ts.findAncestor(node, isConvertableSignatureDeclaration); if (!containingDecl) { return; } var checker = program.getTypeChecker(); var signatureSymbol = containingDecl.symbol; if (!signatureSymbol) { return; } var decls = signatureSymbol.declarations; if (ts.length(decls) <= 1) { return; } if (!ts.every(decls, function (d) { return ts.getSourceFileOfNode(d) === file; })) { return; } if (!isConvertableSignatureDeclaration(decls[0])) { return; } var kindOne = decls[0].kind; if (!ts.every(decls, function (d) { return d.kind === kindOne; })) { return; } var signatureDecls = decls; if (ts.some(signatureDecls, function (d) { return !!d.typeParameters || ts.some(d.parameters, function (p) { return !!p.decorators || !!p.modifiers || !ts.isIdentifier(p.name); }); })) { return; } var signatures = ts.mapDefined(signatureDecls, function (d) { return checker.getSignatureFromDeclaration(d); }); if (ts.length(signatures) !== ts.length(decls)) { return; } var returnOne = checker.getReturnTypeOfSignature(signatures[0]); if (!ts.every(signatures, function (s) { return checker.getReturnTypeOfSignature(s) === returnOne; })) { return; } return signatureDecls; } })(addOrRemoveBracesToArrowFunction = refactor.addOrRemoveBracesToArrowFunction || (refactor.addOrRemoveBracesToArrowFunction = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var extractSymbol; (function (extractSymbol) { var refactorName = "Extract Symbol"; var extractConstantAction = { name: "Extract Constant", description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_constant), kind: "refactor.extract.constant", }; var extractFunctionAction = { name: "Extract Function", description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_function), kind: "refactor.extract.function", }; refactor.registerRefactor(refactorName, { kinds: [ extractConstantAction.kind, extractFunctionAction.kind ], getEditsForAction: getRefactorEditsToExtractSymbol, getAvailableActions: getRefactorActionsToExtractSymbol, }); /** * Compute the associated code actions * Exported for tests. */ function getRefactorActionsToExtractSymbol(context) { var requestedRefactor = context.kind; var rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context), context.triggerReason === "invoked"); var targetRange = rangeToExtract.targetRange; if (targetRange === undefined) { if (!rangeToExtract.errors || rangeToExtract.errors.length === 0 || !context.preferences.provideRefactorNotApplicableReason) { return ts.emptyArray; } var errors = []; if (refactor.refactorKindBeginsWith(extractFunctionAction.kind, requestedRefactor)) { errors.push({ name: refactorName, description: extractFunctionAction.description, actions: [__assign(__assign({}, extractFunctionAction), { notApplicableReason: getStringError(rangeToExtract.errors) })] }); } if (refactor.refactorKindBeginsWith(extractConstantAction.kind, requestedRefactor)) { errors.push({ name: refactorName, description: extractConstantAction.description, actions: [__assign(__assign({}, extractConstantAction), { notApplicableReason: getStringError(rangeToExtract.errors) })] }); } return errors; } var extractions = getPossibleExtractions(targetRange, context); if (extractions === undefined) { // No extractions possible return ts.emptyArray; } var functionActions = []; var usedFunctionNames = new ts.Map(); var innermostErrorFunctionAction; var constantActions = []; var usedConstantNames = new ts.Map(); var innermostErrorConstantAction; 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; var description = functionExtraction.description; if (refactor.refactorKindBeginsWith(extractFunctionAction.kind, requestedRefactor)) { 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 if (!usedFunctionNames.has(description)) { usedFunctionNames.set(description, true); functionActions.push({ description: description, name: "function_scope_".concat(i), kind: extractFunctionAction.kind }); } } else if (!innermostErrorFunctionAction) { innermostErrorFunctionAction = { description: description, name: "function_scope_".concat(i), notApplicableReason: getStringError(functionExtraction.errors), kind: extractFunctionAction.kind }; } } if (refactor.refactorKindBeginsWith(extractConstantAction.kind, requestedRefactor)) { 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_1 = constantExtraction.description; if (!usedConstantNames.has(description_1)) { usedConstantNames.set(description_1, true); constantActions.push({ description: description_1, name: "constant_scope_".concat(i), kind: extractConstantAction.kind }); } } else if (!innermostErrorConstantAction) { innermostErrorConstantAction = { description: description, name: "constant_scope_".concat(i), notApplicableReason: getStringError(constantExtraction.errors), kind: extractConstantAction.kind }; } } // *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 (functionActions.length) { infos.push({ name: refactorName, description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_function), actions: functionActions, }); } else if (context.preferences.provideRefactorNotApplicableReason && innermostErrorFunctionAction) { infos.push({ name: refactorName, description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_function), actions: [innermostErrorFunctionAction] }); } if (constantActions.length) { infos.push({ name: refactorName, description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_constant), actions: constantActions }); } else if (context.preferences.provideRefactorNotApplicableReason && innermostErrorConstantAction) { infos.push({ name: refactorName, description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_constant), actions: [innermostErrorConstantAction] }); } return infos.length ? infos : ts.emptyArray; function getStringError(errors) { var error = errors[0].messageText; if (typeof error !== "string") { error = error.messageText; } return error; } } extractSymbol.getRefactorActionsToExtractSymbol = getRefactorActionsToExtractSymbol; /* Exported for tests */ function getRefactorEditsToExtractSymbol(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.getRefactorEditsToExtractSymbol = getRefactorEditsToExtractSymbol; // 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.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.cannotExtractFunctionsContainingThisToMethod = createMessage("Cannot extract functions containing this to method"); })(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"; RangeFacts[RangeFacts["UsesThisInFunction"] = 16] = "UsesThisInFunction"; /** * The range is in a function which needs the 'static' modifier in a class */ RangeFacts[RangeFacts["InStaticRegion"] = 32] = "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 errors are shown to * users if they have the provideRefactorNotApplicableReason option set. */ // exported only for tests function getRangeToExtract(sourceFile, span, invoked) { if (invoked === void 0) { invoked = true; } var length = span.length; if (length === 0 && !invoked) { return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractEmpty)] }; } var cursorRequest = length === 0 && invoked; var startToken = ts.findFirstNonJsxWhitespaceToken(sourceFile, span.start); var endToken = ts.findTokenOnLeftOfPosition(sourceFile, ts.textSpanEnd(span)); /* If the refactoring command is invoked through a keyboard action it's safe to assume that the user is actively looking for refactoring actions at the span location. As they may not know the exact range that will trigger a refactoring, we expand the searched span to cover a real node range making it more likely that something useful will show up. */ var adjustedSpan = startToken && endToken && invoked ? getAdjustedSpanFromNodes(startToken, endToken, sourceFile) : span; // 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 = cursorRequest ? getExtractableParent(startToken) : ts.getParentNodeInSpan(startToken, sourceFile, adjustedSpan); // Do the same for the ending position var end = cursorRequest ? start : ts.getParentNodeInSpan(endToken, sourceFile, adjustedSpan); 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; var thisNode; if (!start || !end) { // cannot find either start or end node return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } if (start.flags & 8388608 /* NodeFlags.JSDoc */) { return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractJSDoc)] }; } 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 = []; for (var _i = 0, _a = start.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, thisNode: thisNode } }; } 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, thisNode: thisNode } }; // 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) || ts.isVariableDeclarationList(node)) { var declarations_5 = ts.isVariableStatement(node) ? node.declarationList.declarations : node.declarations; var numInitializers = 0; var lastInitializer = void 0; for (var _i = 0, declarations_4 = declarations_5; _i < declarations_4.length; _i++) { var declaration = declarations_4[_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 === 167 /* SyntaxKind.PropertyDeclaration */) { if (ts.isStatic(current)) { rangeFacts |= RangeFacts.InStaticRegion; } break; } else if (current.kind === 164 /* SyntaxKind.Parameter */) { var ctorOrMethod = ts.getContainingFunction(current); if (ctorOrMethod.kind === 171 /* SyntaxKind.Constructor */) { rangeFacts |= RangeFacts.InStaticRegion; } break; } else if (current.kind === 169 /* SyntaxKind.MethodDeclaration */) { if (ts.isStatic(current)) { 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)) && !isStringLiteralJsxAttribute(nodeToCheck)) { return [ts.createDiagnosticForNode(nodeToCheck, Messages.statementOrExpressionExpected)]; } if (nodeToCheck.flags & 16777216 /* NodeFlags.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 /* PermittedJumps.Return */; var seenLabels; visit(nodeToCheck); if (rangeFacts & RangeFacts.UsesThis) { var container = ts.getThisContainer(nodeToCheck, /** includeArrowFunctions */ false); if (container.kind === 256 /* SyntaxKind.FunctionDeclaration */ || (container.kind === 169 /* SyntaxKind.MethodDeclaration */ && container.parent.kind === 205 /* SyntaxKind.ObjectLiteralExpression */) || container.kind === 213 /* SyntaxKind.FunctionExpression */) { rangeFacts |= RangeFacts.UsesThisInFunction; } } return errors; function visit(node) { if (errors) { // already found an error - can stop now return true; } if (ts.isDeclaration(node)) { var declaringNode = (node.kind === 254 /* SyntaxKind.VariableDeclaration */) ? node.parent.parent : node; if (ts.hasSyntacticModifier(declaringNode, 1 /* ModifierFlags.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 266 /* SyntaxKind.ImportDeclaration */: (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractImport)); return true; case 271 /* SyntaxKind.ExportAssignment */: (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); return true; case 106 /* SyntaxKind.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 === 208 /* SyntaxKind.CallExpression */) { // Super constructor call var containingClass_1 = ts.getContainingClass(node); if (containingClass_1 === undefined || 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; thisNode = node; } break; case 214 /* SyntaxKind.ArrowFunction */: // check if arrow function uses this ts.forEachChild(node, function check(n) { if (ts.isThis(n)) { rangeFacts |= RangeFacts.UsesThis; thisNode = node; } else if (ts.isClassLike(n) || (ts.isFunctionLike(n) && !ts.isArrowFunction(n))) { return false; } else { ts.forEachChild(n, check); } }); // falls through case 257 /* SyntaxKind.ClassDeclaration */: case 256 /* SyntaxKind.FunctionDeclaration */: if (ts.isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) { // You cannot extract global declarations (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); } // falls through case 226 /* SyntaxKind.ClassExpression */: case 213 /* SyntaxKind.FunctionExpression */: case 169 /* SyntaxKind.MethodDeclaration */: case 171 /* SyntaxKind.Constructor */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: // do not dive into functions or classes return false; } var savedPermittedJumps = permittedJumps; switch (node.kind) { case 239 /* SyntaxKind.IfStatement */: permittedJumps = 0 /* PermittedJumps.None */; break; case 252 /* SyntaxKind.TryStatement */: // forbid all jumps inside try blocks permittedJumps = 0 /* PermittedJumps.None */; break; case 235 /* SyntaxKind.Block */: if (node.parent && node.parent.kind === 252 /* SyntaxKind.TryStatement */ && node.parent.finallyBlock === node) { // allow unconditional returns from finally blocks permittedJumps = 4 /* PermittedJumps.Return */; } break; case 290 /* SyntaxKind.DefaultClause */: case 289 /* SyntaxKind.CaseClause */: // allow unlabeled break inside case clauses permittedJumps |= 1 /* PermittedJumps.Break */; break; default: if (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false)) { // allow unlabeled break/continue inside loops permittedJumps |= 1 /* PermittedJumps.Break */ | 2 /* PermittedJumps.Continue */; } break; } switch (node.kind) { case 192 /* SyntaxKind.ThisType */: case 108 /* SyntaxKind.ThisKeyword */: rangeFacts |= RangeFacts.UsesThis; thisNode = node; break; case 250 /* SyntaxKind.LabeledStatement */: { var label = node.label; (seenLabels || (seenLabels = [])).push(label.escapedText); ts.forEachChild(node, visit); seenLabels.pop(); break; } case 246 /* SyntaxKind.BreakStatement */: case 245 /* SyntaxKind.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 === 246 /* SyntaxKind.BreakStatement */ ? 1 /* PermittedJumps.Break */ : 2 /* PermittedJumps.Continue */))) { // attempt to break or continue in a forbidden context (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements)); } } break; } case 218 /* SyntaxKind.AwaitExpression */: rangeFacts |= RangeFacts.IsAsyncFunction; break; case 224 /* SyntaxKind.YieldExpression */: rangeFacts |= RangeFacts.IsGenerator; break; case 247 /* SyntaxKind.ReturnStatement */: if (permittedJumps & 4 /* PermittedJumps.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; /** * Includes the final semicolon so that the span covers statements in cases where it would otherwise * only cover the declaration list. */ function getAdjustedSpanFromNodes(startNode, endNode, sourceFile) { var start = startNode.getStart(sourceFile); var end = endNode.getEnd(); if (sourceFile.text.charCodeAt(end) === 59 /* CharacterCodes.semicolon */) { end++; } return { start: start, length: end - start }; } function getStatementOrExpressionRange(node) { if (ts.isStatement(node)) { return [node]; } 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; } if (isStringLiteralJsxAttribute(node)) { return node; } return undefined; } function isScope(node) { return ts.isArrowFunction(node) ? ts.isFunctionBody(node.body) : 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 && !(range.facts & RangeFacts.UsesThisInFunction)) { // 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 === 164 /* SyntaxKind.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 === 305 /* SyntaxKind.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 /* SpecialScope.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 /* SpecialScope.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 171 /* SyntaxKind.Constructor */: return "constructor"; case 213 /* SyntaxKind.FunctionExpression */: case 256 /* SyntaxKind.FunctionDeclaration */: return scope.name ? "function '".concat(scope.name.text, "'") : ts.ANONYMOUS; case 214 /* SyntaxKind.ArrowFunction */: return "arrow function"; case 169 /* SyntaxKind.MethodDeclaration */: return "method '".concat(scope.name.getText(), "'"); case 172 /* SyntaxKind.GetAccessor */: return "'get ".concat(scope.name.getText(), "'"); case 173 /* SyntaxKind.SetAccessor */: return "'set ".concat(scope.name.getText(), "'"); default: throw ts.Debug.assertNever(scope, "Unexpected scope kind ".concat(scope.kind)); } } function getDescriptionForClassLikeDeclaration(scope) { return scope.kind === 257 /* SyntaxKind.ClassDeclaration */ ? scope.name ? "class '".concat(scope.name.text, "'") : "anonymous class declaration" : scope.name ? "class expression '".concat(scope.name.text, "'") : "anonymous class expression"; } function getDescriptionForModuleLikeDeclaration(scope) { return scope.kind === 262 /* SyntaxKind.ModuleBlock */ ? "namespace '".concat(scope.parent.name.getText(), "'") : scope.externalModuleIndicator ? 0 /* SpecialScope.Module */ : 1 /* SpecialScope.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.factory.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 /* NodeBuilderFlags.NoTruncation */); } var paramDecl = ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ name, /*questionToken*/ undefined, typeNode); parameters.push(paramDecl); if (usage.usage === 2 /* Usage.Write */) { (writes || (writes = [])).push(usage); } callArguments.push(ts.factory.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.factory.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 /* NodeBuilderFlags.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; var callThis = !!(range.facts & RangeFacts.UsesThisInFunction); if (ts.isClassLike(scope)) { // always create private method in TypeScript files var modifiers = isJS ? [] : [ts.factory.createModifier(121 /* SyntaxKind.PrivateKeyword */)]; if (range.facts & RangeFacts.InStaticRegion) { modifiers.push(ts.factory.createModifier(124 /* SyntaxKind.StaticKeyword */)); } if (range.facts & RangeFacts.IsAsyncFunction) { modifiers.push(ts.factory.createModifier(131 /* SyntaxKind.AsyncKeyword */)); } newFunction = ts.factory.createMethodDeclaration( /*decorators*/ undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.factory.createToken(41 /* SyntaxKind.AsteriskToken */) : undefined, functionName, /*questionToken*/ undefined, typeParameters, parameters, returnType, body); } else { if (callThis) { parameters.unshift(ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ "this", /*questionToken*/ undefined, checker.typeToTypeNode(checker.getTypeAtLocation(range.thisNode), scope, 1 /* NodeBuilderFlags.NoTruncation */), /*initializer*/ undefined)); } newFunction = ts.factory.createFunctionDeclaration( /*decorators*/ undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.factory.createToken(131 /* SyntaxKind.AsyncKeyword */)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.factory.createToken(41 /* SyntaxKind.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); if (callThis) { callArguments.unshift(ts.factory.createIdentifier("this")); } var call = ts.factory.createCallExpression(callThis ? ts.factory.createPropertyAccessExpression(called, "call") : called, callTypeArguments, // Note that no attempt is made to take advantage of type argument inference callArguments); if (range.facts & RangeFacts.IsGenerator) { call = ts.factory.createYieldExpression(ts.factory.createToken(41 /* SyntaxKind.AsteriskToken */), call); } if (range.facts & RangeFacts.IsAsyncFunction) { call = ts.factory.createAwaitExpression(call); } if (isInJSXContent(node)) { call = ts.factory.createJsxExpression(/*dotDotDotToken*/ undefined, 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.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(ts.getSynthesizedDeepClone(variableDeclaration.name), /*exclamationToken*/ undefined, /*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.factory.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 /* NodeBuilderFlags.NoTruncation */); typeElements.push(ts.factory.createPropertySignature( /*modifiers*/ undefined, /*name*/ variableDeclaration.symbol.name, /*questionToken*/ undefined, /*type*/ variableType)); sawExplicitType = sawExplicitType || variableDeclaration.type !== undefined; commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags; } var typeLiteral = sawExplicitType ? ts.factory.createTypeLiteralNode(typeElements) : undefined; if (typeLiteral) { ts.setEmitFlags(typeLiteral, 1 /* EmitFlags.SingleLine */); } newNodes.push(ts.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(ts.factory.createObjectBindingPattern(bindingElements), /*exclamationToken*/ undefined, /*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 /* NodeFlags.Const */) { flags = (flags & ~2 /* NodeFlags.Const */) | 1 /* NodeFlags.Let */; } newNodes.push(ts.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(variableDeclaration.symbol.name, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); } } if (returnValueProperty) { // has both writes and return, need to create variable declaration to hold return value; newNodes.push(ts.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(returnValueProperty, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(returnType))], 1 /* NodeFlags.Let */))); } var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (returnValueProperty) { assignments.unshift(ts.factory.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.factory.createExpressionStatement(ts.factory.createAssignment(assignments[0].name, call))); if (range.facts & RangeFacts.HasReturn) { newNodes.push(ts.factory.createReturnStatement()); } } else { // emit e.g. // { a, b, __return } = newFunction(a, b); // return __return; newNodes.push(ts.factory.createExpressionStatement(ts.factory.createAssignment(ts.factory.createObjectLiteralExpression(assignments), call))); if (returnValueProperty) { newNodes.push(ts.factory.createReturnStatement(ts.factory.createIdentifier(returnValueProperty))); } } } else { if (range.facts & RangeFacts.HasReturn) { newNodes.push(ts.factory.createReturnStatement(call)); } else if (isReadonlyArray(range.range)) { newNodes.push(ts.factory.createExpressionStatement(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 === 153 /* SyntaxKind.UndefinedKeyword */; }) ? clone : ts.factory.createUnionTypeNode([clone, ts.factory.createKeywordTypeNode(153 /* SyntaxKind.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.isPropertyAccessExpression(node) && !ts.isClassLike(scope) && !checker.resolveName(node.name.text, node, 111551 /* SymbolFlags.Value */, /*excludeGlobals*/ false) && !ts.isPrivateIdentifier(node.name) && !ts.isKeyword(node.name.originalKeywordKind) ? node.name.text : 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 /* NodeBuilderFlags.NoTruncation */); // TODO: GH#18217 var initializer = transformConstantInitializer(ts.skipParentheses(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.factory.createModifier(121 /* SyntaxKind.PrivateKeyword */)); if (rangeFacts & RangeFacts.InStaticRegion) { modifiers.push(ts.factory.createModifier(124 /* SyntaxKind.StaticKeyword */)); } modifiers.push(ts.factory.createModifier(145 /* SyntaxKind.ReadonlyKeyword */)); var newVariable = ts.factory.createPropertyDeclaration( /*decorators*/ undefined, modifiers, localNameText, /*questionToken*/ undefined, variableType, initializer); var localReference = ts.factory.createPropertyAccessExpression(rangeFacts & RangeFacts.InStaticRegion ? ts.factory.createIdentifier(scope.name.getText()) // TODO: GH#18217 : ts.factory.createThis(), ts.factory.createIdentifier(localNameText)); if (isInJSXContent(node)) { localReference = ts.factory.createJsxExpression(/*dotDotDotToken*/ undefined, localReference); } // 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.factory.createVariableDeclaration(localNameText, /*exclamationToken*/ undefined, 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.factory.createIdentifier(localNameText); changeTracker.replaceNode(context.file, node, localReference); } else if (node.parent.kind === 238 /* SyntaxKind.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.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([newVariableDeclaration], 2 /* NodeFlags.Const */)); changeTracker.replaceNode(context.file, node.parent, newVariableStatement); } else { var newVariableStatement = ts.factory.createVariableStatement( /*modifiers*/ undefined, ts.factory.createVariableDeclarationList([newVariableDeclaration], 2 /* NodeFlags.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 === 238 /* SyntaxKind.ExpressionStatement */) { // If the parent is an expression statement, delete it. changeTracker.delete(context.file, node.parent); } else { var localReference = ts.factory.createIdentifier(localNameText); // When extract to a new variable in JSX content, need to wrap a {} out of the new variable // or it will become a plain text if (isInJSXContent(node)) { localReference = ts.factory.createJsxExpression(/*dotDotDotToken*/ undefined, localReference); } 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 /* SignatureKind.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.factory.updateParameterDeclaration(p, p.decorators, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, p.type || checker.typeToTypeNode(paramType, scope, 1 /* NodeBuilderFlags.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.factory.updateArrowFunction(initializer, node.modifiers, initializer.typeParameters, parameters, initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, 1 /* NodeBuilderFlags.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.factory.createParameterDeclaration( /* decorators */ undefined, /* modifiers */ undefined, /* dotDotDotToken */ undefined, "this", /* questionToken */ undefined, checker.typeToTypeNode(thisType, scope, 1 /* NodeBuilderFlags.NoTruncation */))); } } initializer = ts.factory.updateFunctionExpression(initializer, node.modifiers, initializer.asteriskToken, initializer.name, initializer.typeParameters, parameters, initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, 1 /* NodeBuilderFlags.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.factory.createIdentifier(functionNameText); if (ts.isClassLike(scope)) { var lhs = range.facts & RangeFacts.InStaticRegion ? ts.factory.createIdentifier(scope.name.text) : ts.factory.createThis(); // TODO: GH#18217 return ts.factory.createPropertyAccessExpression(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.factory.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } var returnValueProperty; var ignoreReturns = false; var statements = ts.factory.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.factory.createReturnStatement(ts.skipParentheses(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.factory.createReturnStatement(assignments[0].name)); } else { rewrittenStatements.push(ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression(assignments))); } } return { body: ts.factory.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty: returnValueProperty }; } else { return { body: ts.factory.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; } function visitor(node) { if (!ignoreReturns && ts.isReturnStatement(node) && hasWritesOrVariableDeclarations) { var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (node.expression) { if (!returnValueProperty) { returnValueProperty = "__return"; } assignments.unshift(ts.factory.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor))); } if (assignments.length === 1) { return ts.factory.createReturnStatement(assignments[0].name); } else { return ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression(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.factory.createShorthandPropertyAssignment(v.symbol.name); }); var writeAssignments = ts.map(writes, function (w) { return ts.factory.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 = new ts.Map(); // Key is type ID var usagesPerScope = []; var substitutionsPerScope = []; var functionErrorsPerScope = []; var constantErrorsPerScope = []; var visibleDeclarationsInExtractedRange = []; var exposedVariableSymbolSet = new ts.Map(); // 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 /* TypeFlags.Void */ | 131072 /* TypeFlags.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: new ts.Map(), typeParameterUsages: new ts.Map(), substitutions: new ts.Map() }); substitutionsPerScope.push(new ts.Map()); functionErrorsPerScope.push([]); 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 = new ts.Map(); var target = isReadonlyArray(targetRange.range) ? ts.factory.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) && !ts.isJsxAttribute(targetRange.range)) { var contextualType = checker.getContextualType(targetRange.range); // TODO: GH#18217 recordTypeParameterUsages(contextualType); } if (allTypeParameterUsages.size > 0) { var seenTypeParameterUsages = new ts.Map(); // Key is type ID var i_2 = 0; for (var curr = unmodifiedNode; curr !== undefined && i_2 < scopes.length; curr = curr.parent) { if (curr === scopes[i_2]) { // Copy current contents of seenTypeParameterUsages into scope. seenTypeParameterUsages.forEach(function (typeParameter, id) { usagesPerScope[i_2].typeParameterUsages.set(id, typeParameter); }); i_2++; } // 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_2 === 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_18 = 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)); } if (targetRange.facts & RangeFacts.UsesThisInFunction && ts.isClassLike(scopes[i])) { functionErrorsPerScope[i].push(ts.createDiagnosticForNode(targetRange.thisNode, Messages.cannotExtractFunctionsContainingThisToMethod)); } var hasWrite = false; var readonlyClassPropertyWrite; usagesPerScope[i].usages.forEach(function (value) { if (value.usage === 2 /* Usage.Write */) { hasWrite = true; if (value.symbol.flags & 106500 /* SymbolFlags.ClassMember */ && value.symbol.valueDeclaration && ts.hasEffectiveModifier(value.symbol.valueDeclaration, 64 /* ModifierFlags.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_18(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 /* Usage.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 /* Usage.Write */); collectUsages(node.right); } else if (ts.isUnaryExpressionWithWrite(node)) { collectUsages(node.operand, 2 /* Usage.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 to map to simplify rewriting var substitution = substitutionsPerScope[i].get(symbolId); if (substitution) { usagesPerScope[i].substitutions.set(ts.getNodeId(n).toString(), substitution); } } } } function recordUsagebySymbol(identifier, usage, isTypeName) { var symbol = getSymbolReferencedByIdentifier(identifier); if (!symbol) { // cannot find symbol - do nothing return undefined; } var symbolId = ts.getSymbolId(symbol).toString(); var lastUsage = seenUsages.get(symbolId); // there are two kinds of value usages // - reads - if range contains a read from the value located outside of the range then value should be passed as a parameter // - writes - if range contains a write to a value located outside the range the value should be passed as a parameter and // returned as a return value // 'write' case is a superset of 'read' so if we already have processed 'write' of some symbol there is not need to handle 'read' // since all information is already recorded if (lastUsage && lastUsage >= usage) { return symbolId; } seenUsages.set(symbolId, usage); if (lastUsage) { // if we get here this means that we are trying to handle 'write' and 'read' was already processed // walk scopes and update existing records. for (var _i = 0, usagesPerScope_1 = usagesPerScope; _i < usagesPerScope_1.length; _i++) { var perScope = usagesPerScope_1[_i]; var prevEntry = perScope.usages.get(identifier.text); if (prevEntry) { perScope.usages.set(identifier.text, { usage: usage, symbol: symbol, node: identifier }); } } return symbolId; } // find first declaration in this file var decls = symbol.getDeclarations(); var declInFile = decls && ts.find(decls, function (d) { return d.getSourceFile() === sourceFile; }); if (!declInFile) { return undefined; } if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { // declaration is located in range to be extracted - do nothing return undefined; } if (targetRange.facts & RangeFacts.IsGenerator && usage === 2 /* Usage.Write */) { // this is write to a reference located outside of the target scope and range is extracted into generator // currently this is unsupported scenario var diag = ts.createDiagnosticForNode(identifier, Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators); for (var _a = 0, functionErrorsPerScope_1 = functionErrorsPerScope; _a < functionErrorsPerScope_1.length; _a++) { var errors = functionErrorsPerScope_1[_a]; errors.push(diag); } for (var _b = 0, constantErrorsPerScope_1 = constantErrorsPerScope; _b < constantErrorsPerScope_1.length; _b++) { var errors = constantErrorsPerScope_1[_b]; errors.push(diag); } } for (var i = 0; i < scopes.length; i++) { var scope = scopes[i]; var resolvedSymbol = checker.resolveName(symbol.name, scope, symbol.flags, /*excludeGlobals*/ false); if (resolvedSymbol === symbol) { continue; } if (!substitutionsPerScope[i].has(symbolId)) { var substitution = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.exportSymbol || symbol, scope, isTypeName); if (substitution) { substitutionsPerScope[i].set(symbolId, substitution); } else if (isTypeName) { // If the symbol is a type parameter that won't be in scope, we'll pass it as a type argument // so there's no problem. if (!(symbol.flags & 262144 /* SymbolFlags.TypeParameter */)) { var diag = ts.createDiagnosticForNode(identifier, Messages.typeWillNotBeVisibleInTheNewScope); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } } else { usagesPerScope[i].usages.set(identifier.text, { usage: usage, symbol: symbol, node: identifier }); } } } return symbolId; } function checkForUsedDeclarations(node) { // If this node is entirely within the original extraction range, we don't need to do anything. if (node === targetRange.range || (isReadonlyArray(targetRange.range) && targetRange.range.indexOf(node) >= 0)) { return; } // Otherwise check and recurse. var sym = ts.isIdentifier(node) ? getSymbolReferencedByIdentifier(node) : checker.getSymbolAtLocation(node); if (sym) { var decl = ts.find(visibleDeclarationsInExtractedRange, function (d) { return d.symbol === sym; }); if (decl) { if (ts.isVariableDeclaration(decl)) { var idString = decl.symbol.id.toString(); if (!exposedVariableSymbolSet.has(idString)) { exposedVariableDeclarations.push(decl); exposedVariableSymbolSet.set(idString, true); } } else { // CONSIDER: this includes binding elements, which we could // expose in the same way as variables. firstExposedNonVariableDeclaration = firstExposedNonVariableDeclaration || decl; } } } ts.forEachChild(node, checkForUsedDeclarations); } /** * Return the symbol referenced by an identifier (even if it declares a different symbol). */ function getSymbolReferencedByIdentifier(identifier) { // If the identifier is both a property name and its value, we're only interested in its value // (since the name is a declaration and will be included in the extracted range). return identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier ? checker.getShorthandAssignmentValueSymbol(identifier.parent) : checker.getSymbolAtLocation(identifier); } function tryReplaceWithQualifiedNameOrPropertyAccess(symbol, scopeDecl, isTypeNode) { if (!symbol) { return undefined; } var decls = symbol.getDeclarations(); if (decls && decls.some(function (d) { return d.parent === scopeDecl; })) { return ts.factory.createIdentifier(symbol.name); } var prefix = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.parent, scopeDecl, isTypeNode); if (prefix === undefined) { return undefined; } return isTypeNode ? ts.factory.createQualifiedName(prefix, ts.factory.createIdentifier(symbol.name)) : ts.factory.createPropertyAccessExpression(prefix, symbol.name); } } function getExtractableParent(node) { return ts.findAncestor(node, function (node) { return node.parent && isExtractableExpression(node) && !ts.isBinaryExpression(node.parent); }); } /** * Computes whether or not a node represents an expression in a position where it could * be extracted. * The isExpression() in utilities.ts returns some false positives we need to handle, * such as `import x from 'y'` -- the 'y' is a StringLiteral but is *not* an expression * in the sense of something that you could extract on */ function isExtractableExpression(node) { var parent = node.parent; switch (parent.kind) { case 299 /* SyntaxKind.EnumMember */: return false; } switch (node.kind) { case 10 /* SyntaxKind.StringLiteral */: return parent.kind !== 266 /* SyntaxKind.ImportDeclaration */ && parent.kind !== 270 /* SyntaxKind.ImportSpecifier */; case 225 /* SyntaxKind.SpreadElement */: case 201 /* SyntaxKind.ObjectBindingPattern */: case 203 /* SyntaxKind.BindingElement */: return false; case 79 /* SyntaxKind.Identifier */: return parent.kind !== 203 /* SyntaxKind.BindingElement */ && parent.kind !== 270 /* SyntaxKind.ImportSpecifier */ && parent.kind !== 275 /* SyntaxKind.ExportSpecifier */; } return true; } function isBlockLike(node) { switch (node.kind) { case 235 /* SyntaxKind.Block */: case 305 /* SyntaxKind.SourceFile */: case 262 /* SyntaxKind.ModuleBlock */: case 289 /* SyntaxKind.CaseClause */: return true; default: return false; } } function isInJSXContent(node) { return isStringLiteralJsxAttribute(node) || (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node) || ts.isJsxFragment(node)) && (ts.isJsxElement(node.parent) || ts.isJsxFragment(node.parent)); } function isStringLiteralJsxAttribute(node) { return ts.isStringLiteral(node) && node.parent && ts.isJsxAttribute(node.parent); } })(extractSymbol = refactor.extractSymbol || (refactor.extractSymbol = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var refactorName = "Extract type"; var extractToTypeAliasAction = { name: "Extract to type alias", description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_type_alias), kind: "refactor.extract.type", }; var extractToInterfaceAction = { name: "Extract to interface", description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_interface), kind: "refactor.extract.interface", }; var extractToTypeDefAction = { name: "Extract to typedef", description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_typedef), kind: "refactor.extract.typedef" }; refactor.registerRefactor(refactorName, { kinds: [ extractToTypeAliasAction.kind, extractToInterfaceAction.kind, extractToTypeDefAction.kind ], getAvailableActions: function getRefactorActionsToExtractType(context) { var info = getRangeToExtract(context, context.triggerReason === "invoked"); if (!info) return ts.emptyArray; if (!refactor.isRefactorErrorInfo(info)) { return [{ name: refactorName, description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_type), actions: info.isJS ? [extractToTypeDefAction] : ts.append([extractToTypeAliasAction], info.typeElements && extractToInterfaceAction) }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [{ name: refactorName, description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_type), actions: [ __assign(__assign({}, extractToTypeDefAction), { notApplicableReason: info.error }), __assign(__assign({}, extractToTypeAliasAction), { notApplicableReason: info.error }), __assign(__assign({}, extractToInterfaceAction), { notApplicableReason: info.error }), ] }]; } return ts.emptyArray; }, getEditsForAction: function getRefactorEditsToExtractType(context, actionName) { var file = context.file; var info = getRangeToExtract(context); ts.Debug.assert(info && !refactor.isRefactorErrorInfo(info), "Expected to find a range to extract"); var name = ts.getUniqueName("NewType", file); var edits = ts.textChanges.ChangeTracker.with(context, function (changes) { switch (actionName) { case extractToTypeAliasAction.name: ts.Debug.assert(!info.isJS, "Invalid actionName/JS combo"); return doTypeAliasChange(changes, file, name, info); case extractToTypeDefAction.name: ts.Debug.assert(info.isJS, "Invalid actionName/JS combo"); return doTypedefChange(changes, file, name, info); case extractToInterfaceAction.name: ts.Debug.assert(!info.isJS && !!info.typeElements, "Invalid actionName/JS combo"); return doInterfaceChange(changes, file, name, info); default: ts.Debug.fail("Unexpected action name"); } }); var renameFilename = file.fileName; var renameLocation = ts.getRenameLocation(edits, renameFilename, name, /*preferLastLocation*/ false); return { edits: edits, renameFilename: renameFilename, renameLocation: renameLocation }; } }); function getRangeToExtract(context, considerEmptySpans) { if (considerEmptySpans === void 0) { considerEmptySpans = true; } var file = context.file, startPosition = context.startPosition; var isJS = ts.isSourceFileJS(file); var current = ts.getTokenAtPosition(file, startPosition); var range = ts.createTextRangeFromSpan(ts.getRefactorContextSpan(context)); var cursorRequest = range.pos === range.end && considerEmptySpans; var selection = ts.findAncestor(current, (function (node) { return node.parent && ts.isTypeNode(node) && !rangeContainsSkipTrivia(range, node.parent, file) && (cursorRequest || ts.nodeOverlapsWithStartEnd(current, file, range.pos, range.end)); })); if (!selection || !ts.isTypeNode(selection)) return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Selection_is_not_a_valid_type_node) }; var checker = context.program.getTypeChecker(); var firstStatement = ts.Debug.checkDefined(ts.findAncestor(selection, ts.isStatement), "Should find a statement"); var typeParameters = collectTypeParameters(checker, selection, firstStatement, file); if (!typeParameters) return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.No_type_could_be_extracted_from_this_type_node) }; var typeElements = flattenTypeLiteralNodeReference(checker, selection); return { isJS: isJS, selection: selection, firstStatement: firstStatement, typeParameters: typeParameters, typeElements: typeElements }; } function flattenTypeLiteralNodeReference(checker, node) { if (!node) return undefined; if (ts.isIntersectionTypeNode(node)) { var result = []; var seen_1 = new ts.Map(); for (var _i = 0, _a = node.types; _i < _a.length; _i++) { var type = _a[_i]; var flattenedTypeMembers = flattenTypeLiteralNodeReference(checker, type); if (!flattenedTypeMembers || !flattenedTypeMembers.every(function (type) { return type.name && ts.addToSeen(seen_1, ts.getNameFromPropertyName(type.name)); })) { return undefined; } ts.addRange(result, flattenedTypeMembers); } return result; } else if (ts.isParenthesizedTypeNode(node)) { return flattenTypeLiteralNodeReference(checker, node.type); } else if (ts.isTypeLiteralNode(node)) { return node.members; } return undefined; } function rangeContainsSkipTrivia(r1, node, file) { return ts.rangeContainsStartEnd(r1, ts.skipTrivia(file.text, node.pos), node.end); } function collectTypeParameters(checker, selection, statement, file) { var result = []; return visitor(selection) ? undefined : result; function visitor(node) { if (ts.isTypeReferenceNode(node)) { if (ts.isIdentifier(node.typeName)) { var typeName = node.typeName; var symbol = checker.resolveName(typeName.text, typeName, 262144 /* SymbolFlags.TypeParameter */, /* excludeGlobals */ true); for (var _i = 0, _a = (symbol === null || symbol === void 0 ? void 0 : symbol.declarations) || ts.emptyArray; _i < _a.length; _i++) { var decl = _a[_i]; if (ts.isTypeParameterDeclaration(decl) && decl.getSourceFile() === file) { // skip extraction if the type node is in the range of the type parameter declaration. // function foo(): void; if (decl.name.escapedText === typeName.escapedText && rangeContainsSkipTrivia(decl, selection, file)) { return true; } if (rangeContainsSkipTrivia(statement, decl, file) && !rangeContainsSkipTrivia(selection, decl, file)) { ts.pushIfUnique(result, decl); break; } } } } } else if (ts.isInferTypeNode(node)) { var conditionalTypeNode = ts.findAncestor(node, function (n) { return ts.isConditionalTypeNode(n) && rangeContainsSkipTrivia(n.extendsType, node, file); }); if (!conditionalTypeNode || !rangeContainsSkipTrivia(selection, conditionalTypeNode, file)) { return true; } } else if ((ts.isTypePredicateNode(node) || ts.isThisTypeNode(node))) { var functionLikeNode = ts.findAncestor(node.parent, ts.isFunctionLike); if (functionLikeNode && functionLikeNode.type && rangeContainsSkipTrivia(functionLikeNode.type, node, file) && !rangeContainsSkipTrivia(selection, functionLikeNode, file)) { return true; } } else if (ts.isTypeQueryNode(node)) { if (ts.isIdentifier(node.exprName)) { var symbol = checker.resolveName(node.exprName.text, node.exprName, 111551 /* SymbolFlags.Value */, /* excludeGlobals */ false); if ((symbol === null || symbol === void 0 ? void 0 : symbol.valueDeclaration) && rangeContainsSkipTrivia(statement, symbol.valueDeclaration, file) && !rangeContainsSkipTrivia(selection, symbol.valueDeclaration, file)) { return true; } } else { if (ts.isThisIdentifier(node.exprName.left) && !rangeContainsSkipTrivia(selection, node.parent, file)) { return true; } } } if (file && ts.isTupleTypeNode(node) && (ts.getLineAndCharacterOfPosition(file, node.pos).line === ts.getLineAndCharacterOfPosition(file, node.end).line)) { ts.setEmitFlags(node, 1 /* EmitFlags.SingleLine */); } return ts.forEachChild(node, visitor); } } function doTypeAliasChange(changes, file, name, info) { var firstStatement = info.firstStatement, selection = info.selection, typeParameters = info.typeParameters; var newTypeNode = ts.factory.createTypeAliasDeclaration( /* decorators */ undefined, /* modifiers */ undefined, name, typeParameters.map(function (id) { return ts.factory.updateTypeParameterDeclaration(id, id.modifiers, id.name, id.constraint, /* defaultType */ undefined); }), selection); changes.insertNodeBefore(file, firstStatement, ts.ignoreSourceNewlines(newTypeNode), /* blankLineBetween */ true); changes.replaceNode(file, selection, ts.factory.createTypeReferenceNode(name, typeParameters.map(function (id) { return ts.factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined); })), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.ExcludeWhitespace }); } function doInterfaceChange(changes, file, name, info) { var _a; var firstStatement = info.firstStatement, selection = info.selection, typeParameters = info.typeParameters, typeElements = info.typeElements; var newTypeNode = ts.factory.createInterfaceDeclaration( /* decorators */ undefined, /* modifiers */ undefined, name, typeParameters, /* heritageClauses */ undefined, typeElements); ts.setTextRange(newTypeNode, (_a = typeElements[0]) === null || _a === void 0 ? void 0 : _a.parent); changes.insertNodeBefore(file, firstStatement, ts.ignoreSourceNewlines(newTypeNode), /* blankLineBetween */ true); changes.replaceNode(file, selection, ts.factory.createTypeReferenceNode(name, typeParameters.map(function (id) { return ts.factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined); })), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.ExcludeWhitespace }); } function doTypedefChange(changes, file, name, info) { var firstStatement = info.firstStatement, selection = info.selection, typeParameters = info.typeParameters; ts.setEmitFlags(selection, 1536 /* EmitFlags.NoComments */ | 2048 /* EmitFlags.NoNestedComments */); var node = ts.factory.createJSDocTypedefTag(ts.factory.createIdentifier("typedef"), ts.factory.createJSDocTypeExpression(selection), ts.factory.createIdentifier(name)); var templates = []; ts.forEach(typeParameters, function (typeParameter) { var constraint = ts.getEffectiveConstraintOfTypeParameter(typeParameter); var parameter = ts.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, typeParameter.name); var template = ts.factory.createJSDocTemplateTag(ts.factory.createIdentifier("template"), constraint && ts.cast(constraint, ts.isJSDocTypeExpression), [parameter]); templates.push(template); }); changes.insertNodeBefore(file, firstStatement, ts.factory.createJSDocComment(/* comment */ undefined, ts.factory.createNodeArray(ts.concatenate(templates, [node]))), /* blankLineBetween */ true); changes.replaceNode(file, selection, ts.factory.createTypeReferenceNode(name, typeParameters.map(function (id) { return ts.factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined); }))); } })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var generateGetAccessorAndSetAccessor; (function (generateGetAccessorAndSetAccessor) { var actionName = "Generate 'get' and 'set' accessors"; var actionDescription = ts.Diagnostics.Generate_get_and_set_accessors.message; var generateGetSetAction = { name: actionName, description: actionDescription, kind: "refactor.rewrite.property.generateAccessors", }; refactor.registerRefactor(actionName, { kinds: [generateGetSetAction.kind], getEditsForAction: function getRefactorActionsToGenerateGetAndSetAccessors(context, actionName) { if (!context.endPosition) return undefined; var info = ts.codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition); ts.Debug.assert(info && !refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); var edits = ts.codefix.generateAccessorFromProperty(context.file, context.program, context.startPosition, context.endPosition, context, actionName); if (!edits) return undefined; var renameFilename = context.file.fileName; var nameNeedRename = info.renameAccessor ? info.accessorName : info.fieldName; var renameLocationOffset = ts.isIdentifier(nameNeedRename) ? 0 : -1; var renameLocation = renameLocationOffset + ts.getRenameLocation(edits, renameFilename, nameNeedRename.text, /*preferLastLocation*/ ts.isParameter(info.declaration)); return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits }; }, getAvailableActions: function (context) { if (!context.endPosition) return ts.emptyArray; var info = ts.codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition, context.triggerReason === "invoked"); if (!info) return ts.emptyArray; if (!refactor.isRefactorErrorInfo(info)) { return [{ name: actionName, description: actionDescription, actions: [generateGetSetAction], }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [{ name: actionName, description: actionDescription, actions: [__assign(__assign({}, generateGetSetAction), { notApplicableReason: info.error })], }]; } return ts.emptyArray; } }); })(generateGetAccessorAndSetAccessor = refactor.generateGetAccessorAndSetAccessor || (refactor.generateGetAccessorAndSetAccessor = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { ; /** * Checks if some refactor info has refactor error info. */ function isRefactorErrorInfo(info) { return info.error !== undefined; } refactor.isRefactorErrorInfo = isRefactorErrorInfo; /** * Checks if string "known" begins with string "requested". * Used to match requested kinds with a known kind. */ function refactorKindBeginsWith(known, requested) { if (!requested) return true; return known.substr(0, requested.length) === requested; } refactor.refactorKindBeginsWith = refactorKindBeginsWith; })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var refactorName = "Move to a new file"; var description = ts.getLocaleSpecificMessage(ts.Diagnostics.Move_to_a_new_file); var moveToNewFileAction = { name: refactorName, description: description, kind: "refactor.move.newFile", }; refactor.registerRefactor(refactorName, { kinds: [moveToNewFileAction.kind], getAvailableActions: function getRefactorActionsToMoveToNewFile(context) { var statements = getStatementsToMove(context); if (context.preferences.allowTextChangesInNewFiles && statements) { return [{ name: refactorName, description: description, actions: [moveToNewFileAction] }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [{ name: refactorName, description: description, actions: [__assign(__assign({}, moveToNewFileAction), { notApplicableReason: ts.getLocaleSpecificMessage(ts.Diagnostics.Selection_is_not_a_valid_statement_or_statements) })] }]; } return ts.emptyArray; }, getEditsForAction: function getRefactorEditsToMoveToNewFile(context, actionName) { ts.Debug.assert(actionName === refactorName, "Wrong refactor invoked"); var statements = ts.Debug.checkDefined(getStatementsToMove(context)); var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(context.file, context.program, statements, t, context.host, context.preferences); }); return { edits: edits, renameFilename: undefined, renameLocation: undefined }; } }); function getRangeToMove(context) { var file = context.file; var range = ts.createTextRangeFromSpan(ts.getRefactorContextSpan(context)); var statements = file.statements; var startNodeIndex = ts.findIndex(statements, function (s) { return s.end > range.pos; }); if (startNodeIndex === -1) return undefined; var startStatement = statements[startNodeIndex]; if (ts.isNamedDeclaration(startStatement) && startStatement.name && ts.rangeContainsRange(startStatement.name, range)) { return { toMove: [statements[startNodeIndex]], afterLast: statements[startNodeIndex + 1] }; } // Can't only partially include the start node or be partially into the next node if (range.pos > startStatement.getStart(file)) return undefined; var afterEndNodeIndex = ts.findIndex(statements, function (s) { return s.end > range.end; }, startNodeIndex); // Can't be partially into the next node if (afterEndNodeIndex !== -1 && (afterEndNodeIndex === 0 || statements[afterEndNodeIndex].getStart(file) < range.end)) return undefined; return { toMove: statements.slice(startNodeIndex, afterEndNodeIndex === -1 ? statements.length : afterEndNodeIndex), afterLast: afterEndNodeIndex === -1 ? undefined : statements[afterEndNodeIndex], }; } function doChange(oldFile, program, toMove, changes, host, preferences) { var checker = program.getTypeChecker(); var usage = getUsageInfo(oldFile, toMove.all, checker); var currentDirectory = ts.getDirectoryPath(oldFile.fileName); var extension = ts.extensionFromPath(oldFile.fileName); var newModuleName = makeUniqueModuleName(getNewModuleName(usage.movedSymbols), extension, currentDirectory, host); var newFileNameWithExtension = newModuleName + extension; // If previous file was global, this is easy. changes.createNewFile(oldFile, ts.combinePaths(currentDirectory, newFileNameWithExtension), getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, newModuleName, preferences)); addNewFileToTsconfig(program, changes, oldFile.fileName, newFileNameWithExtension, ts.hostGetCanonicalFileName(host)); } function getStatementsToMove(context) { var rangeToMove = getRangeToMove(context); if (rangeToMove === undefined) return undefined; var all = []; var ranges = []; var toMove = rangeToMove.toMove, afterLast = rangeToMove.afterLast; ts.getRangesWhere(toMove, isAllowedStatementToMove, function (start, afterEndIndex) { for (var i = start; i < afterEndIndex; i++) all.push(toMove[i]); ranges.push({ first: toMove[start], afterLast: afterLast }); }); return all.length === 0 ? undefined : { all: all, ranges: ranges }; } function isAllowedStatementToMove(statement) { // Filters imports and prologue directives out of the range of statements to move. // Imports will be copied to the new file anyway, and may still be needed in the old file. // Prologue directives will be copied to the new file and should be left in the old file. return !isPureImport(statement) && !ts.isPrologueDirective(statement); ; } function isPureImport(node) { switch (node.kind) { case 266 /* SyntaxKind.ImportDeclaration */: return true; case 265 /* SyntaxKind.ImportEqualsDeclaration */: return !ts.hasSyntacticModifier(node, 1 /* ModifierFlags.Export */); case 237 /* SyntaxKind.VariableStatement */: return node.declarationList.declarations.every(function (d) { return !!d.initializer && ts.isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true); }); default: return false; } } function addNewFileToTsconfig(program, changes, oldFileName, newFileNameWithExtension, getCanonicalFileName) { var cfg = program.getCompilerOptions().configFile; if (!cfg) return; var newFileAbsolutePath = ts.normalizePath(ts.combinePaths(oldFileName, "..", newFileNameWithExtension)); var newFilePath = ts.getRelativePathFromFile(cfg.fileName, newFileAbsolutePath, getCanonicalFileName); var cfgObject = cfg.statements[0] && ts.tryCast(cfg.statements[0].expression, ts.isObjectLiteralExpression); var filesProp = cfgObject && ts.find(cfgObject.properties, function (prop) { return ts.isPropertyAssignment(prop) && ts.isStringLiteral(prop.name) && prop.name.text === "files"; }); if (filesProp && ts.isArrayLiteralExpression(filesProp.initializer)) { changes.insertNodeInListAfter(cfg, ts.last(filesProp.initializer.elements), ts.factory.createStringLiteral(newFilePath), filesProp.initializer.elements); } } function getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, newModuleName, preferences) { var checker = program.getTypeChecker(); var prologueDirectives = ts.takeWhile(oldFile.statements, ts.isPrologueDirective); if (!oldFile.externalModuleIndicator && !oldFile.commonJsModuleIndicator) { deleteMovedStatements(oldFile, toMove.ranges, changes); return __spreadArray(__spreadArray([], prologueDirectives, true), toMove.all, true); } var useEsModuleSyntax = !!oldFile.externalModuleIndicator; var quotePreference = ts.getQuotePreference(oldFile, preferences); var importsFromNewFile = createOldFileImportsFromNewFile(usage.oldFileImportsFromNewFile, newModuleName, useEsModuleSyntax, quotePreference); if (importsFromNewFile) { ts.insertImports(changes, oldFile, importsFromNewFile, /*blankLineBetween*/ true); } deleteUnusedOldImports(oldFile, toMove.all, changes, usage.unusedImportsFromOldFile, checker); deleteMovedStatements(oldFile, toMove.ranges, changes); updateImportsInOtherFiles(changes, program, oldFile, usage.movedSymbols, newModuleName); var imports = getNewFileImportsAndAddExportInOldFile(oldFile, usage.oldImportsNeededByNewFile, usage.newFileImportsFromOldFile, changes, checker, useEsModuleSyntax, quotePreference); var body = addExports(oldFile, toMove.all, usage.oldFileImportsFromNewFile, useEsModuleSyntax); if (imports.length && body.length) { return __spreadArray(__spreadArray(__spreadArray(__spreadArray([], prologueDirectives, true), imports, true), [ 4 /* SyntaxKind.NewLineTrivia */ ], false), body, true); } return __spreadArray(__spreadArray(__spreadArray([], prologueDirectives, true), imports, true), body, true); } function deleteMovedStatements(sourceFile, moved, changes) { for (var _i = 0, moved_1 = moved; _i < moved_1.length; _i++) { var _a = moved_1[_i], first_1 = _a.first, afterLast = _a.afterLast; changes.deleteNodeRangeExcludingEnd(sourceFile, first_1, afterLast); } } function deleteUnusedOldImports(oldFile, toMove, changes, toDelete, checker) { for (var _i = 0, _a = oldFile.statements; _i < _a.length; _i++) { var statement = _a[_i]; if (ts.contains(toMove, statement)) continue; forEachImportInStatement(statement, function (i) { return deleteUnusedImports(oldFile, i, changes, function (name) { return toDelete.has(checker.getSymbolAtLocation(name)); }); }); } } function updateImportsInOtherFiles(changes, program, oldFile, movedSymbols, newModuleName) { var checker = program.getTypeChecker(); var _loop_19 = function (sourceFile) { if (sourceFile === oldFile) return "continue"; var _loop_20 = function (statement) { forEachImportInStatement(statement, function (importNode) { if (checker.getSymbolAtLocation(moduleSpecifierFromImport(importNode)) !== oldFile.symbol) return; var shouldMove = function (name) { var symbol = ts.isBindingElement(name.parent) ? ts.getPropertySymbolFromBindingElement(checker, name.parent) : ts.skipAlias(checker.getSymbolAtLocation(name), checker); // TODO: GH#18217 return !!symbol && movedSymbols.has(symbol); }; deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file var newModuleSpecifier = ts.combinePaths(ts.getDirectoryPath(moduleSpecifierFromImport(importNode).text), newModuleName); var newImportDeclaration = filterImport(importNode, ts.factory.createStringLiteral(newModuleSpecifier), shouldMove); if (newImportDeclaration) changes.insertNodeAfter(sourceFile, statement, newImportDeclaration); var ns = getNamespaceLikeImport(importNode); if (ns) updateNamespaceLikeImport(changes, sourceFile, checker, movedSymbols, newModuleName, newModuleSpecifier, ns, importNode); }); }; for (var _b = 0, _c = sourceFile.statements; _b < _c.length; _b++) { var statement = _c[_b]; _loop_20(statement); } }; for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { var sourceFile = _a[_i]; _loop_19(sourceFile); } } function getNamespaceLikeImport(node) { switch (node.kind) { case 266 /* SyntaxKind.ImportDeclaration */: return node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === 268 /* SyntaxKind.NamespaceImport */ ? node.importClause.namedBindings.name : undefined; case 265 /* SyntaxKind.ImportEqualsDeclaration */: return node.name; case 254 /* SyntaxKind.VariableDeclaration */: return ts.tryCast(node.name, ts.isIdentifier); default: return ts.Debug.assertNever(node, "Unexpected node kind ".concat(node.kind)); } } function updateNamespaceLikeImport(changes, sourceFile, checker, movedSymbols, newModuleName, newModuleSpecifier, oldImportId, oldImportNode) { var preferredNewNamespaceName = ts.codefix.moduleSpecifierToValidIdentifier(newModuleName, 99 /* ScriptTarget.ESNext */); var needUniqueName = false; var toChange = []; ts.FindAllReferences.Core.eachSymbolReferenceInFile(oldImportId, checker, sourceFile, function (ref) { if (!ts.isPropertyAccessExpression(ref.parent)) return; needUniqueName = needUniqueName || !!checker.resolveName(preferredNewNamespaceName, ref, 67108863 /* SymbolFlags.All */, /*excludeGlobals*/ true); if (movedSymbols.has(checker.getSymbolAtLocation(ref.parent.name))) { toChange.push(ref); } }); if (toChange.length) { var newNamespaceName = needUniqueName ? ts.getUniqueName(preferredNewNamespaceName, sourceFile) : preferredNewNamespaceName; for (var _i = 0, toChange_1 = toChange; _i < toChange_1.length; _i++) { var ref = toChange_1[_i]; changes.replaceNode(sourceFile, ref, ts.factory.createIdentifier(newNamespaceName)); } changes.insertNodeAfter(sourceFile, oldImportNode, updateNamespaceLikeImportNode(oldImportNode, newModuleName, newModuleSpecifier)); } } function updateNamespaceLikeImportNode(node, newNamespaceName, newModuleSpecifier) { var newNamespaceId = ts.factory.createIdentifier(newNamespaceName); var newModuleString = ts.factory.createStringLiteral(newModuleSpecifier); switch (node.kind) { case 266 /* SyntaxKind.ImportDeclaration */: return ts.factory.createImportDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, ts.factory.createNamespaceImport(newNamespaceId)), newModuleString, /*assertClause*/ undefined); case 265 /* SyntaxKind.ImportEqualsDeclaration */: return ts.factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, newNamespaceId, ts.factory.createExternalModuleReference(newModuleString)); case 254 /* SyntaxKind.VariableDeclaration */: return ts.factory.createVariableDeclaration(newNamespaceId, /*exclamationToken*/ undefined, /*type*/ undefined, createRequireCall(newModuleString)); default: return ts.Debug.assertNever(node, "Unexpected node kind ".concat(node.kind)); } } function moduleSpecifierFromImport(i) { return (i.kind === 266 /* SyntaxKind.ImportDeclaration */ ? i.moduleSpecifier : i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */ ? i.moduleReference.expression : i.initializer.arguments[0]); } function forEachImportInStatement(statement, cb) { if (ts.isImportDeclaration(statement)) { if (ts.isStringLiteral(statement.moduleSpecifier)) cb(statement); } else if (ts.isImportEqualsDeclaration(statement)) { if (ts.isExternalModuleReference(statement.moduleReference) && ts.isStringLiteralLike(statement.moduleReference.expression)) { cb(statement); } } else if (ts.isVariableStatement(statement)) { for (var _i = 0, _a = statement.declarationList.declarations; _i < _a.length; _i++) { var decl = _a[_i]; if (decl.initializer && ts.isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true)) { cb(decl); } } } } function createOldFileImportsFromNewFile(newFileNeedExport, newFileNameWithExtension, useEs6Imports, quotePreference) { var defaultImport; var imports = []; newFileNeedExport.forEach(function (symbol) { if (symbol.escapedName === "default" /* InternalSymbolName.Default */) { defaultImport = ts.factory.createIdentifier(ts.symbolNameNoDefault(symbol)); // TODO: GH#18217 } else { imports.push(symbol.name); } }); return makeImportOrRequire(defaultImport, imports, newFileNameWithExtension, useEs6Imports, quotePreference); } function makeImportOrRequire(defaultImport, imports, path, useEs6Imports, quotePreference) { path = ts.ensurePathIsNonModuleName(path); if (useEs6Imports) { var specifiers = imports.map(function (i) { return ts.factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, ts.factory.createIdentifier(i)); }); return ts.makeImportIfNecessary(defaultImport, specifiers, path, quotePreference); } else { ts.Debug.assert(!defaultImport, "No default import should exist"); // If there's a default export, it should have been an es6 module. var bindingElements = imports.map(function (i) { return ts.factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i); }); return bindingElements.length ? makeVariableStatement(ts.factory.createObjectBindingPattern(bindingElements), /*type*/ undefined, createRequireCall(ts.factory.createStringLiteral(path))) : undefined; } } function makeVariableStatement(name, type, initializer, flags) { if (flags === void 0) { flags = 2 /* NodeFlags.Const */; } return ts.factory.createVariableStatement(/*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, initializer)], flags)); } function createRequireCall(moduleSpecifier) { return ts.factory.createCallExpression(ts.factory.createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]); } function addExports(sourceFile, toMove, needExport, useEs6Exports) { return ts.flatMap(toMove, function (statement) { if (isTopLevelDeclarationStatement(statement) && !isExported(sourceFile, statement, useEs6Exports) && forEachTopLevelDeclaration(statement, function (d) { return needExport.has(ts.Debug.checkDefined(d.symbol)); })) { var exports = addExport(statement, useEs6Exports); if (exports) return exports; } return statement; }); } function deleteUnusedImports(sourceFile, importDecl, changes, isUnused) { switch (importDecl.kind) { case 266 /* SyntaxKind.ImportDeclaration */: deleteUnusedImportsInDeclaration(sourceFile, importDecl, changes, isUnused); break; case 265 /* SyntaxKind.ImportEqualsDeclaration */: if (isUnused(importDecl.name)) { changes.delete(sourceFile, importDecl); } break; case 254 /* SyntaxKind.VariableDeclaration */: deleteUnusedImportsInVariableDeclaration(sourceFile, importDecl, changes, isUnused); break; default: ts.Debug.assertNever(importDecl, "Unexpected import decl kind ".concat(importDecl.kind)); } } function deleteUnusedImportsInDeclaration(sourceFile, importDecl, changes, isUnused) { if (!importDecl.importClause) return; var _a = importDecl.importClause, name = _a.name, namedBindings = _a.namedBindings; var defaultUnused = !name || isUnused(name); var namedBindingsUnused = !namedBindings || (namedBindings.kind === 268 /* SyntaxKind.NamespaceImport */ ? isUnused(namedBindings.name) : namedBindings.elements.length !== 0 && namedBindings.elements.every(function (e) { return isUnused(e.name); })); if (defaultUnused && namedBindingsUnused) { changes.delete(sourceFile, importDecl); } else { if (name && defaultUnused) { changes.delete(sourceFile, name); } if (namedBindings) { if (namedBindingsUnused) { changes.replaceNode(sourceFile, importDecl.importClause, ts.factory.updateImportClause(importDecl.importClause, importDecl.importClause.isTypeOnly, name, /*namedBindings*/ undefined)); } else if (namedBindings.kind === 269 /* SyntaxKind.NamedImports */) { for (var _i = 0, _b = namedBindings.elements; _i < _b.length; _i++) { var element = _b[_i]; if (isUnused(element.name)) changes.delete(sourceFile, element); } } } } } function deleteUnusedImportsInVariableDeclaration(sourceFile, varDecl, changes, isUnused) { var name = varDecl.name; switch (name.kind) { case 79 /* SyntaxKind.Identifier */: if (isUnused(name)) { changes.delete(sourceFile, name); } break; case 202 /* SyntaxKind.ArrayBindingPattern */: break; case 201 /* SyntaxKind.ObjectBindingPattern */: if (name.elements.every(function (e) { return ts.isIdentifier(e.name) && isUnused(e.name); })) { changes.delete(sourceFile, ts.isVariableDeclarationList(varDecl.parent) && varDecl.parent.declarations.length === 1 ? varDecl.parent.parent : varDecl); } else { for (var _i = 0, _a = name.elements; _i < _a.length; _i++) { var element = _a[_i]; if (ts.isIdentifier(element.name) && isUnused(element.name)) { changes.delete(sourceFile, element.name); } } } break; } } function getNewFileImportsAndAddExportInOldFile(oldFile, importsToCopy, newFileImportsFromOldFile, changes, checker, useEsModuleSyntax, quotePreference) { var copiedOldImports = []; for (var _i = 0, _a = oldFile.statements; _i < _a.length; _i++) { var oldStatement = _a[_i]; forEachImportInStatement(oldStatement, function (i) { ts.append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), function (name) { return importsToCopy.has(checker.getSymbolAtLocation(name)); })); }); } // Also, import things used from the old file, and insert 'export' modifiers as necessary in the old file. var oldFileDefault; var oldFileNamedImports = []; var markSeenTop = ts.nodeSeenTracker(); // Needed because multiple declarations may appear in `const x = 0, y = 1;`. newFileImportsFromOldFile.forEach(function (symbol) { if (!symbol.declarations) { return; } for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; if (!isTopLevelDeclaration(decl)) continue; var name = nameOfTopLevelDeclaration(decl); if (!name) continue; var top = getTopLevelDeclarationStatement(decl); if (markSeenTop(top)) { addExportToChanges(oldFile, top, name, changes, useEsModuleSyntax); } if (ts.hasSyntacticModifier(decl, 512 /* ModifierFlags.Default */)) { oldFileDefault = name; } else { oldFileNamedImports.push(name.text); } } }); ts.append(copiedOldImports, makeImportOrRequire(oldFileDefault, oldFileNamedImports, ts.removeFileExtension(ts.getBaseFileName(oldFile.fileName)), useEsModuleSyntax, quotePreference)); return copiedOldImports; } function makeUniqueModuleName(moduleName, extension, inDirectory, host) { var newModuleName = moduleName; for (var i = 1;; i++) { var name = ts.combinePaths(inDirectory, newModuleName + extension); if (!host.fileExists(name)) return newModuleName; newModuleName = "".concat(moduleName, ".").concat(i); } } function getNewModuleName(movedSymbols) { return movedSymbols.forEachEntry(ts.symbolNameNoDefault) || "newFile"; } function getUsageInfo(oldFile, toMove, checker) { var movedSymbols = new SymbolSet(); var oldImportsNeededByNewFile = new SymbolSet(); var newFileImportsFromOldFile = new SymbolSet(); var containsJsx = ts.find(toMove, function (statement) { return !!(statement.transformFlags & 2 /* TransformFlags.ContainsJsx */); }); var jsxNamespaceSymbol = getJsxNamespaceSymbol(containsJsx); if (jsxNamespaceSymbol) { // Might not exist (e.g. in non-compiling code) oldImportsNeededByNewFile.add(jsxNamespaceSymbol); } for (var _i = 0, toMove_1 = toMove; _i < toMove_1.length; _i++) { var statement = toMove_1[_i]; forEachTopLevelDeclaration(statement, function (decl) { movedSymbols.add(ts.Debug.checkDefined(ts.isExpressionStatement(decl) ? checker.getSymbolAtLocation(decl.expression.left) : decl.symbol, "Need a symbol here")); }); } for (var _a = 0, toMove_2 = toMove; _a < toMove_2.length; _a++) { var statement = toMove_2[_a]; forEachReference(statement, checker, function (symbol) { if (!symbol.declarations) return; for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) { var decl = _a[_i]; if (isInImport(decl)) { oldImportsNeededByNewFile.add(symbol); } else if (isTopLevelDeclaration(decl) && sourceFileOfTopLevelDeclaration(decl) === oldFile && !movedSymbols.has(symbol)) { newFileImportsFromOldFile.add(symbol); } } }); } var unusedImportsFromOldFile = oldImportsNeededByNewFile.clone(); var oldFileImportsFromNewFile = new SymbolSet(); for (var _b = 0, _c = oldFile.statements; _b < _c.length; _b++) { var statement = _c[_b]; if (ts.contains(toMove, statement)) continue; // jsxNamespaceSymbol will only be set iff it is in oldImportsNeededByNewFile. if (jsxNamespaceSymbol && !!(statement.transformFlags & 2 /* TransformFlags.ContainsJsx */)) { unusedImportsFromOldFile.delete(jsxNamespaceSymbol); } forEachReference(statement, checker, function (symbol) { if (movedSymbols.has(symbol)) oldFileImportsFromNewFile.add(symbol); unusedImportsFromOldFile.delete(symbol); }); } return { movedSymbols: movedSymbols, newFileImportsFromOldFile: newFileImportsFromOldFile, oldFileImportsFromNewFile: oldFileImportsFromNewFile, oldImportsNeededByNewFile: oldImportsNeededByNewFile, unusedImportsFromOldFile: unusedImportsFromOldFile }; function getJsxNamespaceSymbol(containsJsx) { if (containsJsx === undefined) { return undefined; } var jsxNamespace = checker.getJsxNamespace(containsJsx); // Strictly speaking, this could resolve to a symbol other than the JSX namespace. // This will produce erroneous output (probably, an incorrectly copied import) but // is expected to be very rare and easily reversible. var jsxNamespaceSymbol = checker.resolveName(jsxNamespace, containsJsx, 1920 /* SymbolFlags.Namespace */, /*excludeGlobals*/ true); return !!jsxNamespaceSymbol && ts.some(jsxNamespaceSymbol.declarations, isInImport) ? jsxNamespaceSymbol : undefined; } } // Below should all be utilities function isInImport(decl) { switch (decl.kind) { case 265 /* SyntaxKind.ImportEqualsDeclaration */: case 270 /* SyntaxKind.ImportSpecifier */: case 267 /* SyntaxKind.ImportClause */: case 268 /* SyntaxKind.NamespaceImport */: return true; case 254 /* SyntaxKind.VariableDeclaration */: return isVariableDeclarationInImport(decl); case 203 /* SyntaxKind.BindingElement */: return ts.isVariableDeclaration(decl.parent.parent) && isVariableDeclarationInImport(decl.parent.parent); default: return false; } } function isVariableDeclarationInImport(decl) { return ts.isSourceFile(decl.parent.parent.parent) && !!decl.initializer && ts.isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true); } function filterImport(i, moduleSpecifier, keep) { switch (i.kind) { case 266 /* SyntaxKind.ImportDeclaration */: { var clause = i.importClause; if (!clause) return undefined; var defaultImport = clause.name && keep(clause.name) ? clause.name : undefined; var namedBindings = clause.namedBindings && filterNamedBindings(clause.namedBindings, keep); return defaultImport || namedBindings ? ts.factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, ts.factory.createImportClause(/*isTypeOnly*/ false, defaultImport, namedBindings), moduleSpecifier, /*assertClause*/ undefined) : undefined; } case 265 /* SyntaxKind.ImportEqualsDeclaration */: return keep(i.name) ? i : undefined; case 254 /* SyntaxKind.VariableDeclaration */: { var name = filterBindingName(i.name, keep); return name ? makeVariableStatement(name, i.type, createRequireCall(moduleSpecifier), i.parent.flags) : undefined; } default: return ts.Debug.assertNever(i, "Unexpected import kind ".concat(i.kind)); } } function filterNamedBindings(namedBindings, keep) { if (namedBindings.kind === 268 /* SyntaxKind.NamespaceImport */) { return keep(namedBindings.name) ? namedBindings : undefined; } else { var newElements = namedBindings.elements.filter(function (e) { return keep(e.name); }); return newElements.length ? ts.factory.createNamedImports(newElements) : undefined; } } function filterBindingName(name, keep) { switch (name.kind) { case 79 /* SyntaxKind.Identifier */: return keep(name) ? name : undefined; case 202 /* SyntaxKind.ArrayBindingPattern */: return name; case 201 /* SyntaxKind.ObjectBindingPattern */: { // We can't handle nested destructurings or property names well here, so just copy them all. var newElements = name.elements.filter(function (prop) { return prop.propertyName || !ts.isIdentifier(prop.name) || keep(prop.name); }); return newElements.length ? ts.factory.createObjectBindingPattern(newElements) : undefined; } } } function forEachReference(node, checker, onReference) { node.forEachChild(function cb(node) { if (ts.isIdentifier(node) && !ts.isDeclarationName(node)) { var sym = checker.getSymbolAtLocation(node); if (sym) onReference(sym); } else { node.forEachChild(cb); } }); } var SymbolSet = /** @class */ (function () { function SymbolSet() { this.map = new ts.Map(); } SymbolSet.prototype.add = function (symbol) { this.map.set(String(ts.getSymbolId(symbol)), symbol); }; SymbolSet.prototype.has = function (symbol) { return this.map.has(String(ts.getSymbolId(symbol))); }; SymbolSet.prototype.delete = function (symbol) { this.map.delete(String(ts.getSymbolId(symbol))); }; SymbolSet.prototype.forEach = function (cb) { this.map.forEach(cb); }; SymbolSet.prototype.forEachEntry = function (cb) { return ts.forEachEntry(this.map, cb); }; SymbolSet.prototype.clone = function () { var clone = new SymbolSet(); ts.copyEntries(this.map, clone.map); return clone; }; return SymbolSet; }()); function isTopLevelDeclaration(node) { return isNonVariableTopLevelDeclaration(node) && ts.isSourceFile(node.parent) || ts.isVariableDeclaration(node) && ts.isSourceFile(node.parent.parent.parent); } function sourceFileOfTopLevelDeclaration(node) { return ts.isVariableDeclaration(node) ? node.parent.parent.parent : node.parent; } function isTopLevelDeclarationStatement(node) { ts.Debug.assert(ts.isSourceFile(node.parent), "Node parent should be a SourceFile"); return isNonVariableTopLevelDeclaration(node) || ts.isVariableStatement(node); } function isNonVariableTopLevelDeclaration(node) { switch (node.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 265 /* SyntaxKind.ImportEqualsDeclaration */: return true; default: return false; } } function forEachTopLevelDeclaration(statement, cb) { switch (statement.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 265 /* SyntaxKind.ImportEqualsDeclaration */: return cb(statement); case 237 /* SyntaxKind.VariableStatement */: return ts.firstDefined(statement.declarationList.declarations, function (decl) { return forEachTopLevelDeclarationInBindingName(decl.name, cb); }); case 238 /* SyntaxKind.ExpressionStatement */: { var expression = statement.expression; return ts.isBinaryExpression(expression) && ts.getAssignmentDeclarationKind(expression) === 1 /* AssignmentDeclarationKind.ExportsProperty */ ? cb(statement) : undefined; } } } function forEachTopLevelDeclarationInBindingName(name, cb) { switch (name.kind) { case 79 /* SyntaxKind.Identifier */: return cb(ts.cast(name.parent, function (x) { return ts.isVariableDeclaration(x) || ts.isBindingElement(x); })); case 202 /* SyntaxKind.ArrayBindingPattern */: case 201 /* SyntaxKind.ObjectBindingPattern */: return ts.firstDefined(name.elements, function (em) { return ts.isOmittedExpression(em) ? undefined : forEachTopLevelDeclarationInBindingName(em.name, cb); }); default: return ts.Debug.assertNever(name, "Unexpected name kind ".concat(name.kind)); } } function nameOfTopLevelDeclaration(d) { return ts.isExpressionStatement(d) ? ts.tryCast(d.expression.left.name, ts.isIdentifier) : ts.tryCast(d.name, ts.isIdentifier); } function getTopLevelDeclarationStatement(d) { switch (d.kind) { case 254 /* SyntaxKind.VariableDeclaration */: return d.parent.parent; case 203 /* SyntaxKind.BindingElement */: return getTopLevelDeclarationStatement(ts.cast(d.parent.parent, function (p) { return ts.isVariableDeclaration(p) || ts.isBindingElement(p); })); default: return d; } } function addExportToChanges(sourceFile, decl, name, changes, useEs6Exports) { if (isExported(sourceFile, decl, useEs6Exports, name)) return; if (useEs6Exports) { if (!ts.isExpressionStatement(decl)) changes.insertExportModifier(sourceFile, decl); } else { var names = getNamesToExportInCommonJS(decl); if (names.length !== 0) changes.insertNodesAfter(sourceFile, decl, names.map(createExportAssignment)); } } function isExported(sourceFile, decl, useEs6Exports, name) { var _a; if (useEs6Exports) { return !ts.isExpressionStatement(decl) && ts.hasSyntacticModifier(decl, 1 /* ModifierFlags.Export */) || !!(name && ((_a = sourceFile.symbol.exports) === null || _a === void 0 ? void 0 : _a.has(name.escapedText))); } return getNamesToExportInCommonJS(decl).some(function (name) { return sourceFile.symbol.exports.has(ts.escapeLeadingUnderscores(name)); }); } function addExport(decl, useEs6Exports) { return useEs6Exports ? [addEs6Export(decl)] : addCommonjsExport(decl); } function addEs6Export(d) { var modifiers = ts.concatenate([ts.factory.createModifier(93 /* SyntaxKind.ExportKeyword */)], d.modifiers); switch (d.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: return ts.factory.updateFunctionDeclaration(d, d.decorators, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); case 257 /* SyntaxKind.ClassDeclaration */: return ts.factory.updateClassDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); case 237 /* SyntaxKind.VariableStatement */: return ts.factory.updateVariableStatement(d, modifiers, d.declarationList); case 261 /* SyntaxKind.ModuleDeclaration */: return ts.factory.updateModuleDeclaration(d, d.decorators, modifiers, d.name, d.body); case 260 /* SyntaxKind.EnumDeclaration */: return ts.factory.updateEnumDeclaration(d, d.decorators, modifiers, d.name, d.members); case 259 /* SyntaxKind.TypeAliasDeclaration */: return ts.factory.updateTypeAliasDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.type); case 258 /* SyntaxKind.InterfaceDeclaration */: return ts.factory.updateInterfaceDeclaration(d, d.decorators, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); case 265 /* SyntaxKind.ImportEqualsDeclaration */: return ts.factory.updateImportEqualsDeclaration(d, d.decorators, modifiers, d.isTypeOnly, d.name, d.moduleReference); case 238 /* SyntaxKind.ExpressionStatement */: return ts.Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: return ts.Debug.assertNever(d, "Unexpected declaration kind ".concat(d.kind)); } } function addCommonjsExport(decl) { return __spreadArray([decl], getNamesToExportInCommonJS(decl).map(createExportAssignment), true); } function getNamesToExportInCommonJS(decl) { switch (decl.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: return [decl.name.text]; // TODO: GH#18217 case 237 /* SyntaxKind.VariableStatement */: return ts.mapDefined(decl.declarationList.declarations, function (d) { return ts.isIdentifier(d.name) ? d.name.text : undefined; }); case 261 /* SyntaxKind.ModuleDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 265 /* SyntaxKind.ImportEqualsDeclaration */: return ts.emptyArray; case 238 /* SyntaxKind.ExpressionStatement */: return ts.Debug.fail("Can't export an ExpressionStatement"); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: return ts.Debug.assertNever(decl, "Unexpected decl kind ".concat(decl.kind)); } } /** Creates `exports.x = x;` */ function createExportAssignment(name) { return ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("exports"), ts.factory.createIdentifier(name)), 63 /* SyntaxKind.EqualsToken */, ts.factory.createIdentifier(name))); } })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var addOrRemoveBracesToArrowFunction; (function (addOrRemoveBracesToArrowFunction) { var refactorName = "Add or remove braces in an arrow function"; var refactorDescription = ts.Diagnostics.Add_or_remove_braces_in_an_arrow_function.message; var addBracesAction = { name: "Add braces to arrow function", description: ts.Diagnostics.Add_braces_to_arrow_function.message, kind: "refactor.rewrite.arrow.braces.add", }; var removeBracesAction = { name: "Remove braces from arrow function", description: ts.Diagnostics.Remove_braces_from_arrow_function.message, kind: "refactor.rewrite.arrow.braces.remove" }; refactor.registerRefactor(refactorName, { kinds: [removeBracesAction.kind], getEditsForAction: getRefactorEditsToRemoveFunctionBraces, getAvailableActions: getRefactorActionsToRemoveFunctionBraces }); function getRefactorActionsToRemoveFunctionBraces(context) { var file = context.file, startPosition = context.startPosition, triggerReason = context.triggerReason; var info = getConvertibleArrowFunctionAtPosition(file, startPosition, triggerReason === "invoked"); if (!info) return ts.emptyArray; if (!refactor.isRefactorErrorInfo(info)) { return [{ name: refactorName, description: refactorDescription, actions: [ info.addBraces ? addBracesAction : removeBracesAction ] }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [{ name: refactorName, description: refactorDescription, actions: [ __assign(__assign({}, addBracesAction), { notApplicableReason: info.error }), __assign(__assign({}, removeBracesAction), { notApplicableReason: info.error }), ] }]; } return ts.emptyArray; } function getRefactorEditsToRemoveFunctionBraces(context, actionName) { var file = context.file, startPosition = context.startPosition; var info = getConvertibleArrowFunctionAtPosition(file, startPosition); ts.Debug.assert(info && !refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); var expression = info.expression, returnStatement = info.returnStatement, func = info.func; var body; if (actionName === addBracesAction.name) { var returnStatement_1 = ts.factory.createReturnStatement(expression); body = ts.factory.createBlock([returnStatement_1], /* multiLine */ true); ts.copyLeadingComments(expression, returnStatement_1, file, 3 /* SyntaxKind.MultiLineCommentTrivia */, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesAction.name && returnStatement) { var actualExpression = expression || ts.factory.createVoidZero(); body = ts.needsParentheses(actualExpression) ? ts.factory.createParenthesizedExpression(actualExpression) : actualExpression; ts.copyTrailingAsLeadingComments(returnStatement, body, file, 3 /* SyntaxKind.MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); ts.copyLeadingComments(returnStatement, body, file, 3 /* SyntaxKind.MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); ts.copyTrailingComments(returnStatement, body, file, 3 /* SyntaxKind.MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } else { ts.Debug.fail("invalid action"); } var edits = ts.textChanges.ChangeTracker.with(context, function (t) { t.replaceNode(file, func.body, body); }); return { renameFilename: undefined, renameLocation: undefined, edits: edits }; } function getConvertibleArrowFunctionAtPosition(file, startPosition, considerFunctionBodies, kind) { if (considerFunctionBodies === void 0) { considerFunctionBodies = true; } var node = ts.getTokenAtPosition(file, startPosition); var func = ts.getContainingFunction(node); if (!func) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_a_containing_arrow_function) }; } if (!ts.isArrowFunction(func)) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Containing_function_is_not_an_arrow_function) }; } if ((!ts.rangeContainsRange(func, node) || ts.rangeContainsRange(func.body, node) && !considerFunctionBodies)) { return undefined; } if (refactor.refactorKindBeginsWith(addBracesAction.kind, kind) && ts.isExpression(func.body)) { return { func: func, addBraces: true, expression: func.body }; } else if (refactor.refactorKindBeginsWith(removeBracesAction.kind, kind) && ts.isBlock(func.body) && func.body.statements.length === 1) { var firstStatement = ts.first(func.body.statements); if (ts.isReturnStatement(firstStatement)) { return { func: func, addBraces: false, expression: firstStatement.expression, returnStatement: firstStatement }; } } return undefined; } })(addOrRemoveBracesToArrowFunction = refactor.addOrRemoveBracesToArrowFunction || (refactor.addOrRemoveBracesToArrowFunction = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var convertParamsToDestructuredObject; (function (convertParamsToDestructuredObject) { var refactorName = "Convert parameters to destructured object"; var minimumParameterLength = 1; var refactorDescription = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_parameters_to_destructured_object); var toDestructuredAction = { name: refactorName, description: refactorDescription, kind: "refactor.rewrite.parameters.toDestructured" }; refactor.registerRefactor(refactorName, { kinds: [toDestructuredAction.kind], getEditsForAction: getRefactorEditsToConvertParametersToDestructuredObject, getAvailableActions: getRefactorActionsToConvertParametersToDestructuredObject }); function getRefactorActionsToConvertParametersToDestructuredObject(context) { var file = context.file, startPosition = context.startPosition; var isJSFile = ts.isSourceFileJS(file); if (isJSFile) return ts.emptyArray; // TODO: GH#30113 var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, context.program.getTypeChecker()); if (!functionDeclaration) return ts.emptyArray; return [{ name: refactorName, description: refactorDescription, actions: [toDestructuredAction] }]; } function getRefactorEditsToConvertParametersToDestructuredObject(context, actionName) { ts.Debug.assert(actionName === refactorName, "Unexpected action name"); var file = context.file, startPosition = context.startPosition, program = context.program, cancellationToken = context.cancellationToken, host = context.host; var functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, program.getTypeChecker()); if (!functionDeclaration || !cancellationToken) return undefined; var groupedReferences = getGroupedReferences(functionDeclaration, program, cancellationToken); if (groupedReferences.valid) { var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(file, program, host, t, functionDeclaration, groupedReferences); }); return { renameFilename: undefined, renameLocation: undefined, edits: edits }; } return { edits: [] }; // TODO: GH#30113 } function doChange(sourceFile, program, host, changes, functionDeclaration, groupedReferences) { var signature = groupedReferences.signature; var newFunctionDeclarationParams = ts.map(createNewParameters(functionDeclaration, program, host), function (param) { return ts.getSynthesizedDeepClone(param); }); if (signature) { var newSignatureParams = ts.map(createNewParameters(signature, program, host), function (param) { return ts.getSynthesizedDeepClone(param); }); replaceParameters(signature, newSignatureParams); } replaceParameters(functionDeclaration, newFunctionDeclarationParams); var functionCalls = ts.sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ function (a, b) { return ts.compareValues(a.pos, b.pos); }); for (var _i = 0, functionCalls_1 = functionCalls; _i < functionCalls_1.length; _i++) { var call = functionCalls_1[_i]; if (call.arguments && call.arguments.length) { var newArgument = ts.getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true); changes.replaceNodeRange(ts.getSourceFileOfNode(call), ts.first(call.arguments), ts.last(call.arguments), newArgument, { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include }); } } function replaceParameters(declarationOrSignature, parameterDeclarations) { changes.replaceNodeRangeWithNodes(sourceFile, ts.first(declarationOrSignature.parameters), ts.last(declarationOrSignature.parameters), parameterDeclarations, { joiner: ", ", // indentation is set to 0 because otherwise the object parameter will be indented if there is a `this` parameter indentation: 0, leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include }); } } function getGroupedReferences(functionDeclaration, program, cancellationToken) { var functionNames = getFunctionNames(functionDeclaration); var classNames = ts.isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : []; var names = ts.deduplicate(__spreadArray(__spreadArray([], functionNames, true), classNames, true), ts.equateValues); var checker = program.getTypeChecker(); var references = ts.flatMap(names, /*mapfn*/ function (/*mapfn*/ name) { return ts.FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken); }); var groupedReferences = groupReferences(references); if (!ts.every(groupedReferences.declarations, /*callback*/ function (/*callback*/ decl) { return ts.contains(names, decl); })) { groupedReferences.valid = false; } return groupedReferences; function groupReferences(referenceEntries) { var classReferences = { accessExpressions: [], typeUsages: [] }; var groupedReferences = { functionCalls: [], declarations: [], classReferences: classReferences, valid: true }; var functionSymbols = ts.map(functionNames, getSymbolTargetAtLocation); var classSymbols = ts.map(classNames, getSymbolTargetAtLocation); var isConstructor = ts.isConstructorDeclaration(functionDeclaration); var contextualSymbols = ts.map(functionNames, function (name) { return getSymbolForContextualType(name, checker); }); for (var _i = 0, referenceEntries_1 = referenceEntries; _i < referenceEntries_1.length; _i++) { var entry = referenceEntries_1[_i]; if (entry.kind === 0 /* FindAllReferences.EntryKind.Span */) { groupedReferences.valid = false; continue; } /* Declarations in object literals may be implementations of method signatures which have a different symbol from the declaration For example: interface IFoo { m(a: number): void } const foo: IFoo = { m(a: number): void {} } In these cases we get the symbol for the signature from the contextual type. */ if (ts.contains(contextualSymbols, getSymbolTargetAtLocation(entry.node))) { if (isValidMethodSignature(entry.node.parent)) { groupedReferences.signature = entry.node.parent; continue; } var call = entryToFunctionCall(entry); if (call) { groupedReferences.functionCalls.push(call); continue; } } var contextualSymbol = getSymbolForContextualType(entry.node, checker); if (contextualSymbol && ts.contains(contextualSymbols, contextualSymbol)) { var decl = entryToDeclaration(entry); if (decl) { groupedReferences.declarations.push(decl); continue; } } /* We compare symbols because in some cases find all references wil return a reference that may or may not be to the refactored function. Example from the refactorConvertParamsToDestructuredObject_methodCallUnion.ts test: class A { foo(a: number, b: number) { return a + b; } } class B { foo(c: number, d: number) { return c + d; } } declare const ab: A | B; ab.foo(1, 2); Find all references will return `ab.foo(1, 2)` as a reference to A's `foo` but we could be calling B's `foo`. When looking for constructor calls, however, the symbol on the constructor call reference is going to be the corresponding class symbol. So we need to add a special case for this because when calling a constructor of a class through one of its subclasses, the symbols are going to be different. */ if (ts.contains(functionSymbols, getSymbolTargetAtLocation(entry.node)) || ts.isNewExpressionTarget(entry.node)) { var importOrExportReference = entryToImportOrExport(entry); if (importOrExportReference) { continue; } var decl = entryToDeclaration(entry); if (decl) { groupedReferences.declarations.push(decl); continue; } var call = entryToFunctionCall(entry); if (call) { groupedReferences.functionCalls.push(call); continue; } } // if the refactored function is a constructor, we must also check if the references to its class are valid if (isConstructor && ts.contains(classSymbols, getSymbolTargetAtLocation(entry.node))) { var importOrExportReference = entryToImportOrExport(entry); if (importOrExportReference) { continue; } var decl = entryToDeclaration(entry); if (decl) { groupedReferences.declarations.push(decl); continue; } var accessExpression = entryToAccessExpression(entry); if (accessExpression) { classReferences.accessExpressions.push(accessExpression); continue; } // Only class declarations are allowed to be used as a type (in a heritage clause), // otherwise `findAllReferences` might not be able to track constructor calls. if (ts.isClassDeclaration(functionDeclaration.parent)) { var type = entryToType(entry); if (type) { classReferences.typeUsages.push(type); continue; } } } groupedReferences.valid = false; } return groupedReferences; } function getSymbolTargetAtLocation(node) { var symbol = checker.getSymbolAtLocation(node); return symbol && ts.getSymbolTarget(symbol, checker); } } /** * Gets the symbol for the contextual type of the node if it is not a union or intersection. */ function getSymbolForContextualType(node, checker) { var element = ts.getContainingObjectLiteralElement(node); if (element) { var contextualType = checker.getContextualTypeForObjectLiteralElement(element); var symbol = contextualType === null || contextualType === void 0 ? void 0 : contextualType.getSymbol(); if (symbol && !(ts.getCheckFlags(symbol) & 6 /* CheckFlags.Synthetic */)) { return symbol; } } } function entryToImportOrExport(entry) { var node = entry.node; if (ts.isImportSpecifier(node.parent) || ts.isImportClause(node.parent) || ts.isImportEqualsDeclaration(node.parent) || ts.isNamespaceImport(node.parent)) { return node; } if (ts.isExportSpecifier(node.parent) || ts.isExportAssignment(node.parent)) { return node; } return undefined; } function entryToDeclaration(entry) { if (ts.isDeclaration(entry.node.parent)) { return entry.node; } return undefined; } function entryToFunctionCall(entry) { if (entry.node.parent) { var functionReference = entry.node; var parent = functionReference.parent; switch (parent.kind) { // foo(...) or super(...) or new Foo(...) case 208 /* SyntaxKind.CallExpression */: case 209 /* SyntaxKind.NewExpression */: var callOrNewExpression = ts.tryCast(parent, ts.isCallOrNewExpression); if (callOrNewExpression && callOrNewExpression.expression === functionReference) { return callOrNewExpression; } break; // x.foo(...) case 206 /* SyntaxKind.PropertyAccessExpression */: var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); if (propertyAccessExpression && propertyAccessExpression.parent && propertyAccessExpression.name === functionReference) { var callOrNewExpression_1 = ts.tryCast(propertyAccessExpression.parent, ts.isCallOrNewExpression); if (callOrNewExpression_1 && callOrNewExpression_1.expression === propertyAccessExpression) { return callOrNewExpression_1; } } break; // x["foo"](...) case 207 /* SyntaxKind.ElementAccessExpression */: var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); if (elementAccessExpression && elementAccessExpression.parent && elementAccessExpression.argumentExpression === functionReference) { var callOrNewExpression_2 = ts.tryCast(elementAccessExpression.parent, ts.isCallOrNewExpression); if (callOrNewExpression_2 && callOrNewExpression_2.expression === elementAccessExpression) { return callOrNewExpression_2; } } break; } } return undefined; } function entryToAccessExpression(entry) { if (entry.node.parent) { var reference = entry.node; var parent = reference.parent; switch (parent.kind) { // `C.foo` case 206 /* SyntaxKind.PropertyAccessExpression */: var propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); if (propertyAccessExpression && propertyAccessExpression.expression === reference) { return propertyAccessExpression; } break; // `C["foo"]` case 207 /* SyntaxKind.ElementAccessExpression */: var elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); if (elementAccessExpression && elementAccessExpression.expression === reference) { return elementAccessExpression; } break; } } return undefined; } function entryToType(entry) { var reference = entry.node; if (ts.getMeaningFromLocation(reference) === 2 /* SemanticMeaning.Type */ || ts.isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) { return reference; } return undefined; } function getFunctionDeclarationAtPosition(file, startPosition, checker) { var node = ts.getTouchingToken(file, startPosition); var functionDeclaration = ts.getContainingFunctionDeclaration(node); // don't offer refactor on top-level JSDoc if (isTopLevelJSDoc(node)) return undefined; if (functionDeclaration && isValidFunctionDeclaration(functionDeclaration, checker) && ts.rangeContainsRange(functionDeclaration, node) && !(functionDeclaration.body && ts.rangeContainsRange(functionDeclaration.body, node))) return functionDeclaration; return undefined; } function isTopLevelJSDoc(node) { var containingJSDoc = ts.findAncestor(node, ts.isJSDocNode); if (containingJSDoc) { var containingNonJSDoc = ts.findAncestor(containingJSDoc, function (n) { return !ts.isJSDocNode(n); }); return !!containingNonJSDoc && ts.isFunctionLikeDeclaration(containingNonJSDoc); } return false; } function isValidMethodSignature(node) { return ts.isMethodSignature(node) && (ts.isInterfaceDeclaration(node.parent) || ts.isTypeLiteralNode(node.parent)); } function isValidFunctionDeclaration(functionDeclaration, checker) { var _a; if (!isValidParameterNodeArray(functionDeclaration.parameters, checker)) return false; switch (functionDeclaration.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: return hasNameOrDefault(functionDeclaration) && isSingleImplementation(functionDeclaration, checker); case 169 /* SyntaxKind.MethodDeclaration */: if (ts.isObjectLiteralExpression(functionDeclaration.parent)) { var contextualSymbol = getSymbolForContextualType(functionDeclaration.name, checker); // don't offer the refactor when there are multiple signatures since we won't know which ones the user wants to change return ((_a = contextualSymbol === null || contextualSymbol === void 0 ? void 0 : contextualSymbol.declarations) === null || _a === void 0 ? void 0 : _a.length) === 1 && isSingleImplementation(functionDeclaration, checker); } return isSingleImplementation(functionDeclaration, checker); case 171 /* SyntaxKind.Constructor */: if (ts.isClassDeclaration(functionDeclaration.parent)) { return hasNameOrDefault(functionDeclaration.parent) && isSingleImplementation(functionDeclaration, checker); } else { return isValidVariableDeclaration(functionDeclaration.parent.parent) && isSingleImplementation(functionDeclaration, checker); } case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: return isValidVariableDeclaration(functionDeclaration.parent); } return false; } function isSingleImplementation(functionDeclaration, checker) { return !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); } function hasNameOrDefault(functionOrClassDeclaration) { if (!functionOrClassDeclaration.name) { var defaultKeyword = ts.findModifier(functionOrClassDeclaration, 88 /* SyntaxKind.DefaultKeyword */); return !!defaultKeyword; } return true; } function isValidParameterNodeArray(parameters, checker) { return getRefactorableParametersLength(parameters) >= minimumParameterLength && ts.every(parameters, /*callback*/ function (/*callback*/ paramDecl) { return isValidParameterDeclaration(paramDecl, checker); }); } function isValidParameterDeclaration(parameterDeclaration, checker) { if (ts.isRestParameter(parameterDeclaration)) { var type = checker.getTypeAtLocation(parameterDeclaration); if (!checker.isArrayType(type) && !checker.isTupleType(type)) return false; } return !parameterDeclaration.modifiers && !parameterDeclaration.decorators && ts.isIdentifier(parameterDeclaration.name); } function isValidVariableDeclaration(node) { return ts.isVariableDeclaration(node) && ts.isVarConst(node) && ts.isIdentifier(node.name) && !node.type; // TODO: GH#30113 } function hasThisParameter(parameters) { return parameters.length > 0 && ts.isThis(parameters[0].name); } function getRefactorableParametersLength(parameters) { if (hasThisParameter(parameters)) { return parameters.length - 1; } return parameters.length; } function getRefactorableParameters(parameters) { if (hasThisParameter(parameters)) { parameters = ts.factory.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); } return parameters; } function createPropertyOrShorthandAssignment(name, initializer) { if (ts.isIdentifier(initializer) && ts.getTextOfIdentifierOrLiteral(initializer) === name) { return ts.factory.createShorthandPropertyAssignment(name); } return ts.factory.createPropertyAssignment(name, initializer); } function createNewArgument(functionDeclaration, functionArguments) { var parameters = getRefactorableParameters(functionDeclaration.parameters); var hasRestParameter = ts.isRestParameter(ts.last(parameters)); var nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments; var properties = ts.map(nonRestArguments, function (arg, i) { var parameterName = getParameterName(parameters[i]); var property = createPropertyOrShorthandAssignment(parameterName, arg); ts.suppressLeadingAndTrailingTrivia(property.name); if (ts.isPropertyAssignment(property)) ts.suppressLeadingAndTrailingTrivia(property.initializer); ts.copyComments(arg, property); return property; }); if (hasRestParameter && functionArguments.length >= parameters.length) { var restArguments = functionArguments.slice(parameters.length - 1); var restProperty = ts.factory.createPropertyAssignment(getParameterName(ts.last(parameters)), ts.factory.createArrayLiteralExpression(restArguments)); properties.push(restProperty); } var objectLiteral = ts.factory.createObjectLiteralExpression(properties, /*multiLine*/ false); return objectLiteral; } function createNewParameters(functionDeclaration, program, host) { var checker = program.getTypeChecker(); var refactorableParameters = getRefactorableParameters(functionDeclaration.parameters); var bindingElements = ts.map(refactorableParameters, createBindingElementFromParameterDeclaration); var objectParameterName = ts.factory.createObjectBindingPattern(bindingElements); var objectParameterType = createParameterTypeNode(refactorableParameters); var objectInitializer; // If every parameter in the original function was optional, add an empty object initializer to the new object parameter if (ts.every(refactorableParameters, isOptionalParameter)) { objectInitializer = ts.factory.createObjectLiteralExpression(); } var objectParameter = ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, objectParameterName, /*questionToken*/ undefined, objectParameterType, objectInitializer); if (hasThisParameter(functionDeclaration.parameters)) { var thisParameter = functionDeclaration.parameters[0]; var newThisParameter = ts.factory.createParameterDeclaration( /*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, thisParameter.name, /*questionToken*/ undefined, thisParameter.type); ts.suppressLeadingAndTrailingTrivia(newThisParameter.name); ts.copyComments(thisParameter.name, newThisParameter.name); if (thisParameter.type) { ts.suppressLeadingAndTrailingTrivia(newThisParameter.type); ts.copyComments(thisParameter.type, newThisParameter.type); } return ts.factory.createNodeArray([newThisParameter, objectParameter]); } return ts.factory.createNodeArray([objectParameter]); function createBindingElementFromParameterDeclaration(parameterDeclaration) { var element = ts.factory.createBindingElement( /*dotDotDotToken*/ undefined, /*propertyName*/ undefined, getParameterName(parameterDeclaration), ts.isRestParameter(parameterDeclaration) && isOptionalParameter(parameterDeclaration) ? ts.factory.createArrayLiteralExpression() : parameterDeclaration.initializer); ts.suppressLeadingAndTrailingTrivia(element); if (parameterDeclaration.initializer && element.initializer) { ts.copyComments(parameterDeclaration.initializer, element.initializer); } return element; } function createParameterTypeNode(parameters) { var members = ts.map(parameters, createPropertySignatureFromParameterDeclaration); var typeNode = ts.addEmitFlags(ts.factory.createTypeLiteralNode(members), 1 /* EmitFlags.SingleLine */); return typeNode; } function createPropertySignatureFromParameterDeclaration(parameterDeclaration) { var parameterType = parameterDeclaration.type; if (!parameterType && (parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration))) { parameterType = getTypeNode(parameterDeclaration); } var propertySignature = ts.factory.createPropertySignature( /*modifiers*/ undefined, getParameterName(parameterDeclaration), isOptionalParameter(parameterDeclaration) ? ts.factory.createToken(57 /* SyntaxKind.QuestionToken */) : parameterDeclaration.questionToken, parameterType); ts.suppressLeadingAndTrailingTrivia(propertySignature); ts.copyComments(parameterDeclaration.name, propertySignature.name); if (parameterDeclaration.type && propertySignature.type) { ts.copyComments(parameterDeclaration.type, propertySignature.type); } return propertySignature; } function getTypeNode(node) { var type = checker.getTypeAtLocation(node); return ts.getTypeNodeIfAccessible(type, node, program, host); } function isOptionalParameter(parameterDeclaration) { if (ts.isRestParameter(parameterDeclaration)) { var type = checker.getTypeAtLocation(parameterDeclaration); return !checker.isTupleType(type); } return checker.isOptionalParameter(parameterDeclaration); } } function getParameterName(paramDeclaration) { return ts.getTextOfIdentifierOrLiteral(paramDeclaration.name); } function getClassNames(constructorDeclaration) { switch (constructorDeclaration.parent.kind) { case 257 /* SyntaxKind.ClassDeclaration */: var classDeclaration = constructorDeclaration.parent; if (classDeclaration.name) return [classDeclaration.name]; // If the class declaration doesn't have a name, it should have a default modifier. // We validated this in `isValidFunctionDeclaration` through `hasNameOrDefault` var defaultModifier = ts.Debug.checkDefined(ts.findModifier(classDeclaration, 88 /* SyntaxKind.DefaultKeyword */), "Nameless class declaration should be a default export"); return [defaultModifier]; case 226 /* SyntaxKind.ClassExpression */: var classExpression = constructorDeclaration.parent; var variableDeclaration = constructorDeclaration.parent.parent; var className = classExpression.name; if (className) return [className, variableDeclaration.name]; return [variableDeclaration.name]; } } function getFunctionNames(functionDeclaration) { switch (functionDeclaration.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: if (functionDeclaration.name) return [functionDeclaration.name]; // If the function declaration doesn't have a name, it should have a default modifier. // We validated this in `isValidFunctionDeclaration` through `hasNameOrDefault` var defaultModifier = ts.Debug.checkDefined(ts.findModifier(functionDeclaration, 88 /* SyntaxKind.DefaultKeyword */), "Nameless function declaration should be a default export"); return [defaultModifier]; case 169 /* SyntaxKind.MethodDeclaration */: return [functionDeclaration.name]; case 171 /* SyntaxKind.Constructor */: var ctrKeyword = ts.Debug.checkDefined(ts.findChildOfKind(functionDeclaration, 134 /* SyntaxKind.ConstructorKeyword */, functionDeclaration.getSourceFile()), "Constructor declaration should have constructor keyword"); if (functionDeclaration.parent.kind === 226 /* SyntaxKind.ClassExpression */) { var variableDeclaration = functionDeclaration.parent.parent; return [variableDeclaration.name, ctrKeyword]; } return [ctrKeyword]; case 214 /* SyntaxKind.ArrowFunction */: return [functionDeclaration.parent.name]; case 213 /* SyntaxKind.FunctionExpression */: if (functionDeclaration.name) return [functionDeclaration.name, functionDeclaration.parent.name]; return [functionDeclaration.parent.name]; default: return ts.Debug.assertNever(functionDeclaration, "Unexpected function declaration kind ".concat(functionDeclaration.kind)); } } })(convertParamsToDestructuredObject = refactor.convertParamsToDestructuredObject || (refactor.convertParamsToDestructuredObject = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var convertStringOrTemplateLiteral; (function (convertStringOrTemplateLiteral) { var refactorName = "Convert to template string"; var refactorDescription = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_template_string); var convertStringAction = { name: refactorName, description: refactorDescription, kind: "refactor.rewrite.string" }; refactor.registerRefactor(refactorName, { kinds: [convertStringAction.kind], getEditsForAction: getRefactorEditsToConvertToTemplateString, getAvailableActions: getRefactorActionsToConvertToTemplateString }); function getRefactorActionsToConvertToTemplateString(context) { var file = context.file, startPosition = context.startPosition; var node = getNodeOrParentOfParentheses(file, startPosition); var maybeBinary = getParentBinaryExpression(node); var refactorInfo = { name: refactorName, description: refactorDescription, actions: [] }; if (ts.isBinaryExpression(maybeBinary) && treeToArray(maybeBinary).isValidConcatenation) { refactorInfo.actions.push(convertStringAction); return [refactorInfo]; } else if (context.preferences.provideRefactorNotApplicableReason) { refactorInfo.actions.push(__assign(__assign({}, convertStringAction), { notApplicableReason: ts.getLocaleSpecificMessage(ts.Diagnostics.Can_only_convert_string_concatenation) })); return [refactorInfo]; } return ts.emptyArray; } function getNodeOrParentOfParentheses(file, startPosition) { var node = ts.getTokenAtPosition(file, startPosition); var nestedBinary = getParentBinaryExpression(node); var isNonStringBinary = !treeToArray(nestedBinary).isValidConcatenation; if (isNonStringBinary && ts.isParenthesizedExpression(nestedBinary.parent) && ts.isBinaryExpression(nestedBinary.parent.parent)) { return nestedBinary.parent.parent; } return node; } function getRefactorEditsToConvertToTemplateString(context, actionName) { var file = context.file, startPosition = context.startPosition; var node = getNodeOrParentOfParentheses(file, startPosition); switch (actionName) { case refactorDescription: return { edits: getEditsForToTemplateLiteral(context, node) }; default: return ts.Debug.fail("invalid action"); } } function getEditsForToTemplateLiteral(context, node) { var maybeBinary = getParentBinaryExpression(node); var file = context.file; var templateLiteral = nodesToTemplate(treeToArray(maybeBinary), file); var trailingCommentRanges = ts.getTrailingCommentRanges(file.text, maybeBinary.end); if (trailingCommentRanges) { var lastComment = trailingCommentRanges[trailingCommentRanges.length - 1]; var trailingRange_1 = { pos: trailingCommentRanges[0].pos, end: lastComment.end }; // since suppressTrailingTrivia(maybeBinary) does not work, the trailing comment is removed manually // otherwise it would have the trailing comment twice return ts.textChanges.ChangeTracker.with(context, function (t) { t.deleteRange(file, trailingRange_1); t.replaceNode(file, maybeBinary, templateLiteral); }); } else { return ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceNode(file, maybeBinary, templateLiteral); }); } } function isNotEqualsOperator(node) { return node.operatorToken.kind !== 63 /* SyntaxKind.EqualsToken */; } function getParentBinaryExpression(expr) { var container = ts.findAncestor(expr.parent, function (n) { switch (n.kind) { case 206 /* SyntaxKind.PropertyAccessExpression */: case 207 /* SyntaxKind.ElementAccessExpression */: return false; case 223 /* SyntaxKind.TemplateExpression */: case 221 /* SyntaxKind.BinaryExpression */: return !(ts.isBinaryExpression(n.parent) && isNotEqualsOperator(n.parent)); default: return "quit"; } }); return (container || expr); } function treeToArray(current) { var loop = function (current) { if (!ts.isBinaryExpression(current)) { return { nodes: [current], operators: [], validOperators: true, hasString: ts.isStringLiteral(current) || ts.isNoSubstitutionTemplateLiteral(current) }; } var _a = loop(current.left), nodes = _a.nodes, operators = _a.operators, leftHasString = _a.hasString, leftOperatorValid = _a.validOperators; if (!(leftHasString || ts.isStringLiteral(current.right) || ts.isTemplateExpression(current.right))) { return { nodes: [current], operators: [], hasString: false, validOperators: true }; } var currentOperatorValid = current.operatorToken.kind === 39 /* SyntaxKind.PlusToken */; var validOperators = leftOperatorValid && currentOperatorValid; nodes.push(current.right); operators.push(current.operatorToken); return { nodes: nodes, operators: operators, hasString: true, validOperators: validOperators }; }; var _a = loop(current), nodes = _a.nodes, operators = _a.operators, validOperators = _a.validOperators, hasString = _a.hasString; return { nodes: nodes, operators: operators, isValidConcatenation: validOperators && hasString }; } // to copy comments following the operator // "foo" + /* comment */ "bar" var copyTrailingOperatorComments = function (operators, file) { return function (index, targetNode) { if (index < operators.length) { ts.copyTrailingComments(operators[index], targetNode, file, 3 /* SyntaxKind.MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } }; }; // to copy comments following the string // "foo" /* comment */ + "bar" /* comment */ + "bar2" var copyCommentFromMultiNode = function (nodes, file, copyOperatorComments) { return function (indexes, targetNode) { while (indexes.length > 0) { var index = indexes.shift(); ts.copyTrailingComments(nodes[index], targetNode, file, 3 /* SyntaxKind.MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); copyOperatorComments(index, targetNode); } }; }; function escapeRawStringForTemplate(s) { // Escaping for $s in strings that are to be used in template strings // Naive implementation: replace \x by itself and otherwise $ and ` by \$ and \`. // But to complicate it a bit, this should work for raw strings too. return s.replace(/\\.|[$`]/g, function (m) { return m[0] === "\\" ? m : "\\" + m; }); // Finally, a less-backslash-happy version can work too, doing only ${ instead of all $s: // s.replace(/\\.|\${|`/g, m => m[0] === "\\" ? m : "\\" + m); // but `\$${foo}` is likely more clear than the more-confusing-but-still-working `$${foo}`. } function getRawTextOfTemplate(node) { // in these cases the right side is ${ var rightShaving = ts.isTemplateHead(node) || ts.isTemplateMiddle(node) ? -2 : -1; return ts.getTextOfNode(node).slice(1, rightShaving); } function concatConsecutiveString(index, nodes) { var indexes = []; var text = "", rawText = ""; while (index < nodes.length) { var node = nodes[index]; if (ts.isStringLiteralLike(node)) { // includes isNoSubstitutionTemplateLiteral(node) text += node.text; rawText += escapeRawStringForTemplate(ts.getTextOfNode(node).slice(1, -1)); indexes.push(index); index++; } else if (ts.isTemplateExpression(node)) { text += node.head.text; rawText += getRawTextOfTemplate(node.head); break; } else { break; } } return [index, text, rawText, indexes]; } function nodesToTemplate(_a, file) { var nodes = _a.nodes, operators = _a.operators; var copyOperatorComments = copyTrailingOperatorComments(operators, file); var copyCommentFromStringLiterals = copyCommentFromMultiNode(nodes, file, copyOperatorComments); var _b = concatConsecutiveString(0, nodes), begin = _b[0], headText = _b[1], rawHeadText = _b[2], headIndexes = _b[3]; if (begin === nodes.length) { var noSubstitutionTemplateLiteral = ts.factory.createNoSubstitutionTemplateLiteral(headText, rawHeadText); copyCommentFromStringLiterals(headIndexes, noSubstitutionTemplateLiteral); return noSubstitutionTemplateLiteral; } var templateSpans = []; var templateHead = ts.factory.createTemplateHead(headText, rawHeadText); copyCommentFromStringLiterals(headIndexes, templateHead); var _loop_21 = function (i) { var currentNode = getExpressionFromParenthesesOrExpression(nodes[i]); copyOperatorComments(i, currentNode); var _c = concatConsecutiveString(i + 1, nodes), newIndex = _c[0], subsequentText = _c[1], rawSubsequentText = _c[2], stringIndexes = _c[3]; i = newIndex - 1; var isLast = i === nodes.length - 1; if (ts.isTemplateExpression(currentNode)) { var spans = ts.map(currentNode.templateSpans, function (span, index) { copyExpressionComments(span); var isLastSpan = index === currentNode.templateSpans.length - 1; var text = span.literal.text + (isLastSpan ? subsequentText : ""); var rawText = getRawTextOfTemplate(span.literal) + (isLastSpan ? rawSubsequentText : ""); return ts.factory.createTemplateSpan(span.expression, isLast && isLastSpan ? ts.factory.createTemplateTail(text, rawText) : ts.factory.createTemplateMiddle(text, rawText)); }); templateSpans.push.apply(templateSpans, spans); } else { var templatePart = isLast ? ts.factory.createTemplateTail(subsequentText, rawSubsequentText) : ts.factory.createTemplateMiddle(subsequentText, rawSubsequentText); copyCommentFromStringLiterals(stringIndexes, templatePart); templateSpans.push(ts.factory.createTemplateSpan(currentNode, templatePart)); } out_i_1 = i; }; var out_i_1; for (var i = begin; i < nodes.length; i++) { _loop_21(i); i = out_i_1; } return ts.factory.createTemplateExpression(templateHead, templateSpans); } // to copy comments following the opening & closing parentheses // "foo" + ( /* comment */ 5 + 5 ) /* comment */ + "bar" function copyExpressionComments(node) { var file = node.getSourceFile(); ts.copyTrailingComments(node, node.expression, file, 3 /* SyntaxKind.MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); ts.copyTrailingAsLeadingComments(node.expression, node.expression, file, 3 /* SyntaxKind.MultiLineCommentTrivia */, /* hasTrailingNewLine */ false); } function getExpressionFromParenthesesOrExpression(node) { if (ts.isParenthesizedExpression(node)) { copyExpressionComments(node); node = node.expression; } return node; } })(convertStringOrTemplateLiteral = refactor.convertStringOrTemplateLiteral || (refactor.convertStringOrTemplateLiteral = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var convertArrowFunctionOrFunctionExpression; (function (convertArrowFunctionOrFunctionExpression) { var refactorName = "Convert arrow function or function expression"; var refactorDescription = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_arrow_function_or_function_expression); var toAnonymousFunctionAction = { name: "Convert to anonymous function", description: ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_anonymous_function), kind: "refactor.rewrite.function.anonymous", }; var toNamedFunctionAction = { name: "Convert to named function", description: ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_named_function), kind: "refactor.rewrite.function.named", }; var toArrowFunctionAction = { name: "Convert to arrow function", description: ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_arrow_function), kind: "refactor.rewrite.function.arrow", }; refactor.registerRefactor(refactorName, { kinds: [ toAnonymousFunctionAction.kind, toNamedFunctionAction.kind, toArrowFunctionAction.kind ], getEditsForAction: getRefactorEditsToConvertFunctionExpressions, getAvailableActions: getRefactorActionsToConvertFunctionExpressions }); function getRefactorActionsToConvertFunctionExpressions(context) { var file = context.file, startPosition = context.startPosition, program = context.program, kind = context.kind; var info = getFunctionInfo(file, startPosition, program); if (!info) return ts.emptyArray; var selectedVariableDeclaration = info.selectedVariableDeclaration, func = info.func; var possibleActions = []; var errors = []; if (refactor.refactorKindBeginsWith(toNamedFunctionAction.kind, kind)) { var error = selectedVariableDeclaration || (ts.isArrowFunction(func) && ts.isVariableDeclaration(func.parent)) ? undefined : ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_convert_to_named_function); if (error) { errors.push(__assign(__assign({}, toNamedFunctionAction), { notApplicableReason: error })); } else { possibleActions.push(toNamedFunctionAction); } } if (refactor.refactorKindBeginsWith(toAnonymousFunctionAction.kind, kind)) { var error = !selectedVariableDeclaration && ts.isArrowFunction(func) ? undefined : ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_convert_to_anonymous_function); if (error) { errors.push(__assign(__assign({}, toAnonymousFunctionAction), { notApplicableReason: error })); } else { possibleActions.push(toAnonymousFunctionAction); } } if (refactor.refactorKindBeginsWith(toArrowFunctionAction.kind, kind)) { var error = ts.isFunctionExpression(func) ? undefined : ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_convert_to_arrow_function); if (error) { errors.push(__assign(__assign({}, toArrowFunctionAction), { notApplicableReason: error })); } else { possibleActions.push(toArrowFunctionAction); } } return [{ name: refactorName, description: refactorDescription, actions: possibleActions.length === 0 && context.preferences.provideRefactorNotApplicableReason ? errors : possibleActions }]; } function getRefactorEditsToConvertFunctionExpressions(context, actionName) { var file = context.file, startPosition = context.startPosition, program = context.program; var info = getFunctionInfo(file, startPosition, program); if (!info) return undefined; var func = info.func; var edits = []; switch (actionName) { case toAnonymousFunctionAction.name: edits.push.apply(edits, getEditInfoForConvertToAnonymousFunction(context, func)); break; case toNamedFunctionAction.name: var variableInfo = getVariableInfo(func); if (!variableInfo) return undefined; edits.push.apply(edits, getEditInfoForConvertToNamedFunction(context, func, variableInfo)); break; case toArrowFunctionAction.name: if (!ts.isFunctionExpression(func)) return undefined; edits.push.apply(edits, getEditInfoForConvertToArrowFunction(context, func)); break; default: return ts.Debug.fail("invalid action"); } return { renameFilename: undefined, renameLocation: undefined, edits: edits }; } function containingThis(node) { var containsThis = false; node.forEachChild(function checkThis(child) { if (ts.isThis(child)) { containsThis = true; return; } if (!ts.isClassLike(child) && !ts.isFunctionDeclaration(child) && !ts.isFunctionExpression(child)) { ts.forEachChild(child, checkThis); } }); return containsThis; } function getFunctionInfo(file, startPosition, program) { var token = ts.getTokenAtPosition(file, startPosition); var typeChecker = program.getTypeChecker(); var func = tryGetFunctionFromVariableDeclaration(file, typeChecker, token.parent); if (func && !containingThis(func.body) && !typeChecker.containsArgumentsReference(func)) { return { selectedVariableDeclaration: true, func: func }; } var maybeFunc = ts.getContainingFunction(token); if (maybeFunc && (ts.isFunctionExpression(maybeFunc) || ts.isArrowFunction(maybeFunc)) && !ts.rangeContainsRange(maybeFunc.body, token) && !containingThis(maybeFunc.body) && !typeChecker.containsArgumentsReference(maybeFunc)) { if (ts.isFunctionExpression(maybeFunc) && isFunctionReferencedInFile(file, typeChecker, maybeFunc)) return undefined; return { selectedVariableDeclaration: false, func: maybeFunc }; } return undefined; } function isSingleVariableDeclaration(parent) { return ts.isVariableDeclaration(parent) || (ts.isVariableDeclarationList(parent) && parent.declarations.length === 1); } function tryGetFunctionFromVariableDeclaration(sourceFile, typeChecker, parent) { if (!isSingleVariableDeclaration(parent)) { return undefined; } var variableDeclaration = ts.isVariableDeclaration(parent) ? parent : ts.first(parent.declarations); var initializer = variableDeclaration.initializer; if (initializer && (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer) && !isFunctionReferencedInFile(sourceFile, typeChecker, initializer))) { return initializer; } return undefined; } function convertToBlock(body) { if (ts.isExpression(body)) { var returnStatement = ts.factory.createReturnStatement(body); var file = body.getSourceFile(); ts.suppressLeadingAndTrailingTrivia(returnStatement); ts.copyTrailingAsLeadingComments(body, returnStatement, file, /* commentKind */ undefined, /* hasTrailingNewLine */ true); return ts.factory.createBlock([returnStatement], /* multiLine */ true); } else { return body; } } function getVariableInfo(func) { var variableDeclaration = func.parent; if (!ts.isVariableDeclaration(variableDeclaration) || !ts.isVariableDeclarationInVariableStatement(variableDeclaration)) return undefined; var variableDeclarationList = variableDeclaration.parent; var statement = variableDeclarationList.parent; if (!ts.isVariableDeclarationList(variableDeclarationList) || !ts.isVariableStatement(statement) || !ts.isIdentifier(variableDeclaration.name)) return undefined; return { variableDeclaration: variableDeclaration, variableDeclarationList: variableDeclarationList, statement: statement, name: variableDeclaration.name }; } function getEditInfoForConvertToAnonymousFunction(context, func) { var file = context.file; var body = convertToBlock(func.body); var newNode = ts.factory.createFunctionExpression(func.modifiers, func.asteriskToken, /* name */ undefined, func.typeParameters, func.parameters, func.type, body); return ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceNode(file, func, newNode); }); } function getEditInfoForConvertToNamedFunction(context, func, variableInfo) { var file = context.file; var body = convertToBlock(func.body); var variableDeclaration = variableInfo.variableDeclaration, variableDeclarationList = variableInfo.variableDeclarationList, statement = variableInfo.statement, name = variableInfo.name; ts.suppressLeadingTrivia(statement); var modifiersFlags = (ts.getCombinedModifierFlags(variableDeclaration) & 1 /* ModifierFlags.Export */) | ts.getEffectiveModifierFlags(func); var modifiers = ts.factory.createModifiersFromModifierFlags(modifiersFlags); var newNode = ts.factory.createFunctionDeclaration(func.decorators, ts.length(modifiers) ? modifiers : undefined, func.asteriskToken, name, func.typeParameters, func.parameters, func.type, body); if (variableDeclarationList.declarations.length === 1) { return ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceNode(file, statement, newNode); }); } else { return ts.textChanges.ChangeTracker.with(context, function (t) { t.delete(file, variableDeclaration); t.insertNodeAfter(file, statement, newNode); }); } } function getEditInfoForConvertToArrowFunction(context, func) { var file = context.file; var statements = func.body.statements; var head = statements[0]; var body; if (canBeConvertedToExpression(func.body, head)) { body = head.expression; ts.suppressLeadingAndTrailingTrivia(body); ts.copyComments(head, body); } else { body = func.body; } var newNode = ts.factory.createArrowFunction(func.modifiers, func.typeParameters, func.parameters, func.type, ts.factory.createToken(38 /* SyntaxKind.EqualsGreaterThanToken */), body); return ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceNode(file, func, newNode); }); } function canBeConvertedToExpression(body, head) { return body.statements.length === 1 && ((ts.isReturnStatement(head) && !!head.expression)); } function isFunctionReferencedInFile(sourceFile, typeChecker, node) { return !!node.name && ts.FindAllReferences.Core.isSymbolReferencedInFile(node.name, typeChecker, sourceFile); } })(convertArrowFunctionOrFunctionExpression = refactor.convertArrowFunctionOrFunctionExpression || (refactor.convertArrowFunctionOrFunctionExpression = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var refactor; (function (refactor) { var inferFunctionReturnType; (function (inferFunctionReturnType) { var refactorName = "Infer function return type"; var refactorDescription = ts.Diagnostics.Infer_function_return_type.message; var inferReturnTypeAction = { name: refactorName, description: refactorDescription, kind: "refactor.rewrite.function.returnType" }; refactor.registerRefactor(refactorName, { kinds: [inferReturnTypeAction.kind], getEditsForAction: getRefactorEditsToInferReturnType, getAvailableActions: getRefactorActionsToInferReturnType }); function getRefactorEditsToInferReturnType(context) { var info = getInfo(context); if (info && !refactor.isRefactorErrorInfo(info)) { var edits = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(context.file, t, info.declaration, info.returnTypeNode); }); return { renameFilename: undefined, renameLocation: undefined, edits: edits }; } return undefined; } function getRefactorActionsToInferReturnType(context) { var info = getInfo(context); if (!info) return ts.emptyArray; if (!refactor.isRefactorErrorInfo(info)) { return [{ name: refactorName, description: refactorDescription, actions: [inferReturnTypeAction] }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [{ name: refactorName, description: refactorDescription, actions: [__assign(__assign({}, inferReturnTypeAction), { notApplicableReason: info.error })] }]; } return ts.emptyArray; } function doChange(sourceFile, changes, declaration, typeNode) { var closeParen = ts.findChildOfKind(declaration, 21 /* SyntaxKind.CloseParenToken */, sourceFile); var needParens = ts.isArrowFunction(declaration) && closeParen === undefined; var endNode = needParens ? ts.first(declaration.parameters) : closeParen; if (endNode) { if (needParens) { changes.insertNodeBefore(sourceFile, endNode, ts.factory.createToken(20 /* SyntaxKind.OpenParenToken */)); changes.insertNodeAfter(sourceFile, endNode, ts.factory.createToken(21 /* SyntaxKind.CloseParenToken */)); } changes.insertNodeAt(sourceFile, endNode.end, typeNode, { prefix: ": " }); } } function getInfo(context) { if (ts.isInJSFile(context.file) || !refactor.refactorKindBeginsWith(inferReturnTypeAction.kind, context.kind)) return; var token = ts.getTokenAtPosition(context.file, context.startPosition); var declaration = ts.findAncestor(token, function (n) { return ts.isBlock(n) || n.parent && ts.isArrowFunction(n.parent) && (n.kind === 38 /* SyntaxKind.EqualsGreaterThanToken */ || n.parent.body === n) ? "quit" : isConvertibleDeclaration(n); }); if (!declaration || !declaration.body || declaration.type) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Return_type_must_be_inferred_from_a_function) }; } var typeChecker = context.program.getTypeChecker(); var returnType = tryGetReturnType(typeChecker, declaration); if (!returnType) { return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_determine_function_return_type) }; } var returnTypeNode = typeChecker.typeToTypeNode(returnType, declaration, 1 /* NodeBuilderFlags.NoTruncation */); if (returnTypeNode) { return { declaration: declaration, returnTypeNode: returnTypeNode }; } } function isConvertibleDeclaration(node) { switch (node.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: case 169 /* SyntaxKind.MethodDeclaration */: return true; default: return false; } } function tryGetReturnType(typeChecker, node) { if (typeChecker.isImplementationOfOverload(node)) { var signatures = typeChecker.getTypeAtLocation(node).getCallSignatures(); if (signatures.length > 1) { return typeChecker.getUnionType(ts.mapDefined(signatures, function (s) { return s.getReturnType(); })); } } var signature = typeChecker.getSignatureFromDeclaration(node); if (signature) { return typeChecker.getReturnTypeOfSignature(signature); } } })(inferFunctionReturnType = refactor.inferFunctionReturnType || (refactor.inferFunctionReturnType = {})); })(refactor = ts.refactor || (ts.refactor = {})); })(ts || (ts = {})); var ts; (function (ts) { /** The version of the language service API */ ts.servicesVersion = "0.8"; function createNode(kind, pos, end, parent) { var node = ts.isNodeKind(kind) ? new NodeObject(kind, pos, end) : kind === 79 /* SyntaxKind.Identifier */ ? new IdentifierObject(79 /* SyntaxKind.Identifier */, pos, end) : kind === 80 /* SyntaxKind.PrivateIdentifier */ ? new PrivateIdentifierObject(80 /* SyntaxKind.PrivateIdentifier */, pos, end) : new TokenObject(kind, pos, end); node.parent = parent; node.flags = parent.flags & 50720768 /* NodeFlags.ContextFlags */; return node; } var NodeObject = /** @class */ (function () { function NodeObject(kind, pos, end) { this.pos = pos; this.end = end; this.flags = 0 /* NodeFlags.None */; this.modifierFlagsCache = 0 /* ModifierFlags.None */; this.transformFlags = 0 /* TransformFlags.None */; this.parent = undefined; this.kind = kind; } NodeObject.prototype.assertHasRealPosition = function (message) { // eslint-disable-next-line debug-assert ts.Debug.assert(!ts.positionIsSynthesized(this.pos) && !ts.positionIsSynthesized(this.end), message || "Node must have a real position for this operation"); }; NodeObject.prototype.getSourceFile = function () { return ts.getSourceFileOfNode(this); }; NodeObject.prototype.getStart = function (sourceFile, includeJsDocComment) { this.assertHasRealPosition(); return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); }; NodeObject.prototype.getFullStart = function () { this.assertHasRealPosition(); return this.pos; }; NodeObject.prototype.getEnd = function () { this.assertHasRealPosition(); return this.end; }; NodeObject.prototype.getWidth = function (sourceFile) { this.assertHasRealPosition(); return this.getEnd() - this.getStart(sourceFile); }; NodeObject.prototype.getFullWidth = function () { this.assertHasRealPosition(); return this.end - this.pos; }; NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) { this.assertHasRealPosition(); return this.getStart(sourceFile) - this.pos; }; NodeObject.prototype.getFullText = function (sourceFile) { this.assertHasRealPosition(); return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); }; NodeObject.prototype.getText = function (sourceFile) { this.assertHasRealPosition(); if (!sourceFile) { sourceFile = this.getSourceFile(); } return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd()); }; NodeObject.prototype.getChildCount = function (sourceFile) { return this.getChildren(sourceFile).length; }; NodeObject.prototype.getChildAt = function (index, sourceFile) { return this.getChildren(sourceFile)[index]; }; NodeObject.prototype.getChildren = function (sourceFile) { this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine"); return this._children || (this._children = createChildren(this, sourceFile)); }; NodeObject.prototype.getFirstToken = function (sourceFile) { this.assertHasRealPosition(); var children = this.getChildren(sourceFile); if (!children.length) { return undefined; } var child = ts.find(children, function (kid) { return kid.kind < 309 /* SyntaxKind.FirstJSDocNode */ || kid.kind > 347 /* SyntaxKind.LastJSDocNode */; }); return child.kind < 161 /* SyntaxKind.FirstNode */ ? child : child.getFirstToken(sourceFile); }; NodeObject.prototype.getLastToken = function (sourceFile) { this.assertHasRealPosition(); var children = this.getChildren(sourceFile); var child = ts.lastOrUndefined(children); if (!child) { return undefined; } return child.kind < 161 /* SyntaxKind.FirstNode */ ? child : child.getLastToken(sourceFile); }; NodeObject.prototype.forEachChild = function (cbNode, cbNodeArray) { return ts.forEachChild(this, cbNode, cbNodeArray); }; return NodeObject; }()); function createChildren(node, sourceFile) { if (!ts.isNodeKind(node.kind)) { return ts.emptyArray; } var children = []; if (ts.isJSDocCommentContainingNode(node)) { /** Don't add trivia for "tokens" since this is in a comment. */ node.forEachChild(function (child) { children.push(child); }); return children; } ts.scanner.setText((sourceFile || node.getSourceFile()).text); var pos = node.pos; var processNode = function (child) { addSyntheticNodes(children, pos, child.pos, node); children.push(child); pos = child.end; }; var processNodes = function (nodes) { addSyntheticNodes(children, pos, nodes.pos, node); children.push(createSyntaxList(nodes, node)); pos = nodes.end; }; // jsDocComments need to be the first children ts.forEach(node.jsDoc, processNode); // For syntactic classifications, all trivia are classified together, including jsdoc comments. // For that to work, the jsdoc comments should still be the leading trivia of the first child. // Restoring the scanner position ensures that. pos = node.pos; node.forEachChild(processNode, processNodes); addSyntheticNodes(children, pos, node.end, node); ts.scanner.setText(undefined); return children; } function addSyntheticNodes(nodes, pos, end, parent) { ts.scanner.setTextPos(pos); while (pos < end) { var token = ts.scanner.scan(); var textPos = ts.scanner.getTextPos(); if (textPos <= end) { if (token === 79 /* SyntaxKind.Identifier */) { ts.Debug.fail("Did not expect ".concat(ts.Debug.formatSyntaxKind(parent.kind), " to have an Identifier in its trivia")); } nodes.push(createNode(token, pos, textPos, parent)); } pos = textPos; if (token === 1 /* SyntaxKind.EndOfFileToken */) { break; } } } function createSyntaxList(nodes, parent) { var list = createNode(348 /* SyntaxKind.SyntaxList */, nodes.pos, nodes.end, parent); list._children = []; var pos = nodes.pos; for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) { var node = nodes_2[_i]; addSyntheticNodes(list._children, pos, node.pos, parent); list._children.push(node); pos = node.end; } addSyntheticNodes(list._children, pos, nodes.end, parent); return list; } var TokenOrIdentifierObject = /** @class */ (function () { function TokenOrIdentifierObject(pos, end) { // Set properties in same order as NodeObject this.pos = pos; this.end = end; this.flags = 0 /* NodeFlags.None */; this.modifierFlagsCache = 0 /* ModifierFlags.None */; this.transformFlags = 0 /* TransformFlags.None */; this.parent = undefined; } TokenOrIdentifierObject.prototype.getSourceFile = function () { return ts.getSourceFileOfNode(this); }; TokenOrIdentifierObject.prototype.getStart = function (sourceFile, includeJsDocComment) { return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); }; TokenOrIdentifierObject.prototype.getFullStart = function () { return this.pos; }; TokenOrIdentifierObject.prototype.getEnd = function () { return this.end; }; TokenOrIdentifierObject.prototype.getWidth = function (sourceFile) { return this.getEnd() - this.getStart(sourceFile); }; TokenOrIdentifierObject.prototype.getFullWidth = function () { return this.end - this.pos; }; TokenOrIdentifierObject.prototype.getLeadingTriviaWidth = function (sourceFile) { return this.getStart(sourceFile) - this.pos; }; TokenOrIdentifierObject.prototype.getFullText = function (sourceFile) { return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); }; TokenOrIdentifierObject.prototype.getText = function (sourceFile) { if (!sourceFile) { sourceFile = this.getSourceFile(); } return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd()); }; TokenOrIdentifierObject.prototype.getChildCount = function () { return this.getChildren().length; }; TokenOrIdentifierObject.prototype.getChildAt = function (index) { return this.getChildren()[index]; }; TokenOrIdentifierObject.prototype.getChildren = function () { return this.kind === 1 /* SyntaxKind.EndOfFileToken */ ? this.jsDoc || ts.emptyArray : ts.emptyArray; }; TokenOrIdentifierObject.prototype.getFirstToken = function () { return undefined; }; TokenOrIdentifierObject.prototype.getLastToken = function () { return undefined; }; TokenOrIdentifierObject.prototype.forEachChild = function () { return undefined; }; return TokenOrIdentifierObject; }()); var SymbolObject = /** @class */ (function () { function SymbolObject(flags, name) { this.flags = flags; this.escapedName = name; } SymbolObject.prototype.getFlags = function () { return this.flags; }; Object.defineProperty(SymbolObject.prototype, "name", { get: function () { return ts.symbolName(this); }, enumerable: false, configurable: true }); SymbolObject.prototype.getEscapedName = function () { return this.escapedName; }; SymbolObject.prototype.getName = function () { return this.name; }; SymbolObject.prototype.getDeclarations = function () { return this.declarations; }; SymbolObject.prototype.getDocumentationComment = function (checker) { if (!this.documentationComment) { this.documentationComment = ts.emptyArray; // Set temporarily to avoid an infinite loop finding inherited docs if (!this.declarations && this.target && this.target.tupleLabelDeclaration) { var labelDecl = this.target.tupleLabelDeclaration; this.documentationComment = getDocumentationComment([labelDecl], checker); } else { this.documentationComment = getDocumentationComment(this.declarations, checker); } } return this.documentationComment; }; SymbolObject.prototype.getContextualDocumentationComment = function (context, checker) { switch (context === null || context === void 0 ? void 0 : context.kind) { case 172 /* SyntaxKind.GetAccessor */: if (!this.contextualGetAccessorDocumentationComment) { this.contextualGetAccessorDocumentationComment = getDocumentationComment(ts.filter(this.declarations, ts.isGetAccessor), checker); } return this.contextualGetAccessorDocumentationComment; case 173 /* SyntaxKind.SetAccessor */: if (!this.contextualSetAccessorDocumentationComment) { this.contextualSetAccessorDocumentationComment = getDocumentationComment(ts.filter(this.declarations, ts.isSetAccessor), checker); } return this.contextualSetAccessorDocumentationComment; default: return this.getDocumentationComment(checker); } }; SymbolObject.prototype.getJsDocTags = function (checker) { if (this.tags === undefined) { this.tags = getJsDocTagsOfDeclarations(this.declarations, checker); } return this.tags; }; SymbolObject.prototype.getContextualJsDocTags = function (context, checker) { switch (context === null || context === void 0 ? void 0 : context.kind) { case 172 /* SyntaxKind.GetAccessor */: if (!this.contextualGetAccessorTags) { this.contextualGetAccessorTags = getJsDocTagsOfDeclarations(ts.filter(this.declarations, ts.isGetAccessor), checker); } return this.contextualGetAccessorTags; case 173 /* SyntaxKind.SetAccessor */: if (!this.contextualSetAccessorTags) { this.contextualSetAccessorTags = getJsDocTagsOfDeclarations(ts.filter(this.declarations, ts.isSetAccessor), checker); } return this.contextualSetAccessorTags; default: return this.getJsDocTags(checker); } }; return SymbolObject; }()); var TokenObject = /** @class */ (function (_super) { __extends(TokenObject, _super); function TokenObject(kind, pos, end) { var _this = _super.call(this, pos, end) || this; _this.kind = kind; return _this; } return TokenObject; }(TokenOrIdentifierObject)); var IdentifierObject = /** @class */ (function (_super) { __extends(IdentifierObject, _super); function IdentifierObject(_kind, pos, end) { var _this = _super.call(this, pos, end) || this; _this.kind = 79 /* SyntaxKind.Identifier */; return _this; } Object.defineProperty(IdentifierObject.prototype, "text", { get: function () { return ts.idText(this); }, enumerable: false, configurable: true }); return IdentifierObject; }(TokenOrIdentifierObject)); IdentifierObject.prototype.kind = 79 /* SyntaxKind.Identifier */; var PrivateIdentifierObject = /** @class */ (function (_super) { __extends(PrivateIdentifierObject, _super); function PrivateIdentifierObject(_kind, pos, end) { return _super.call(this, pos, end) || this; } Object.defineProperty(PrivateIdentifierObject.prototype, "text", { get: function () { return ts.idText(this); }, enumerable: false, configurable: true }); return PrivateIdentifierObject; }(TokenOrIdentifierObject)); PrivateIdentifierObject.prototype.kind = 80 /* SyntaxKind.PrivateIdentifier */; var TypeObject = /** @class */ (function () { function TypeObject(checker, flags) { this.checker = checker; this.flags = flags; } TypeObject.prototype.getFlags = function () { return this.flags; }; TypeObject.prototype.getSymbol = function () { return this.symbol; }; TypeObject.prototype.getProperties = function () { return this.checker.getPropertiesOfType(this); }; TypeObject.prototype.getProperty = function (propertyName) { return this.checker.getPropertyOfType(this, propertyName); }; TypeObject.prototype.getApparentProperties = function () { return this.checker.getAugmentedPropertiesOfType(this); }; TypeObject.prototype.getCallSignatures = function () { return this.checker.getSignaturesOfType(this, 0 /* SignatureKind.Call */); }; TypeObject.prototype.getConstructSignatures = function () { return this.checker.getSignaturesOfType(this, 1 /* SignatureKind.Construct */); }; TypeObject.prototype.getStringIndexType = function () { return this.checker.getIndexTypeOfType(this, 0 /* IndexKind.String */); }; TypeObject.prototype.getNumberIndexType = function () { return this.checker.getIndexTypeOfType(this, 1 /* IndexKind.Number */); }; TypeObject.prototype.getBaseTypes = function () { return this.isClassOrInterface() ? this.checker.getBaseTypes(this) : undefined; }; TypeObject.prototype.isNullableType = function () { return this.checker.isNullableType(this); }; TypeObject.prototype.getNonNullableType = function () { return this.checker.getNonNullableType(this); }; TypeObject.prototype.getNonOptionalType = function () { return this.checker.getNonOptionalType(this); }; TypeObject.prototype.getConstraint = function () { return this.checker.getBaseConstraintOfType(this); }; TypeObject.prototype.getDefault = function () { return this.checker.getDefaultFromTypeParameter(this); }; TypeObject.prototype.isUnion = function () { return !!(this.flags & 1048576 /* TypeFlags.Union */); }; TypeObject.prototype.isIntersection = function () { return !!(this.flags & 2097152 /* TypeFlags.Intersection */); }; TypeObject.prototype.isUnionOrIntersection = function () { return !!(this.flags & 3145728 /* TypeFlags.UnionOrIntersection */); }; TypeObject.prototype.isLiteral = function () { return !!(this.flags & 384 /* TypeFlags.StringOrNumberLiteral */); }; TypeObject.prototype.isStringLiteral = function () { return !!(this.flags & 128 /* TypeFlags.StringLiteral */); }; TypeObject.prototype.isNumberLiteral = function () { return !!(this.flags & 256 /* TypeFlags.NumberLiteral */); }; TypeObject.prototype.isTypeParameter = function () { return !!(this.flags & 262144 /* TypeFlags.TypeParameter */); }; TypeObject.prototype.isClassOrInterface = function () { return !!(ts.getObjectFlags(this) & 3 /* ObjectFlags.ClassOrInterface */); }; TypeObject.prototype.isClass = function () { return !!(ts.getObjectFlags(this) & 1 /* ObjectFlags.Class */); }; TypeObject.prototype.isIndexType = function () { return !!(this.flags & 4194304 /* TypeFlags.Index */); }; Object.defineProperty(TypeObject.prototype, "typeArguments", { /** * This polyfills `referenceType.typeArguments` for API consumers */ get: function () { if (ts.getObjectFlags(this) & 4 /* ObjectFlags.Reference */) { return this.checker.getTypeArguments(this); } return undefined; }, enumerable: false, configurable: true }); return TypeObject; }()); var SignatureObject = /** @class */ (function () { function SignatureObject(checker, flags) { this.checker = checker; this.flags = flags; } SignatureObject.prototype.getDeclaration = function () { return this.declaration; }; SignatureObject.prototype.getTypeParameters = function () { return this.typeParameters; }; SignatureObject.prototype.getParameters = function () { return this.parameters; }; SignatureObject.prototype.getReturnType = function () { return this.checker.getReturnTypeOfSignature(this); }; SignatureObject.prototype.getTypeParameterAtPosition = function (pos) { var type = this.checker.getParameterType(this, pos); if (type.isIndexType() && ts.isThisTypeParameter(type.type)) { var constraint = type.type.getConstraint(); if (constraint) { return this.checker.getIndexType(constraint); } } return type; }; SignatureObject.prototype.getDocumentationComment = function () { return this.documentationComment || (this.documentationComment = getDocumentationComment(ts.singleElementArray(this.declaration), this.checker)); }; SignatureObject.prototype.getJsDocTags = function () { return this.jsDocTags || (this.jsDocTags = getJsDocTagsOfDeclarations(ts.singleElementArray(this.declaration), this.checker)); }; return SignatureObject; }()); /** * Returns whether or not the given node has a JSDoc "inheritDoc" tag on it. * @param node the Node in question. * @returns `true` if `node` has a JSDoc "inheritDoc" tag on it, otherwise `false`. */ function hasJSDocInheritDocTag(node) { return ts.getJSDocTags(node).some(function (tag) { return tag.tagName.text === "inheritDoc"; }); } function getJsDocTagsOfDeclarations(declarations, checker) { if (!declarations) return ts.emptyArray; var tags = ts.JsDoc.getJsDocTagsFromDeclarations(declarations, checker); if (checker && (tags.length === 0 || declarations.some(hasJSDocInheritDocTag))) { var seenSymbols_1 = new ts.Set(); var _loop_22 = function (declaration) { var inheritedTags = findBaseOfDeclaration(checker, declaration, function (symbol) { var _a; if (!seenSymbols_1.has(symbol)) { seenSymbols_1.add(symbol); if (declaration.kind === 172 /* SyntaxKind.GetAccessor */ || declaration.kind === 173 /* SyntaxKind.SetAccessor */) { return symbol.getContextualJsDocTags(declaration, checker); } return ((_a = symbol.declarations) === null || _a === void 0 ? void 0 : _a.length) === 1 ? symbol.getJsDocTags() : undefined; } }); if (inheritedTags) { tags = __spreadArray(__spreadArray([], inheritedTags, true), tags, true); } }; for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { var declaration = declarations_6[_i]; _loop_22(declaration); } } return tags; } function getDocumentationComment(declarations, checker) { if (!declarations) return ts.emptyArray; var doc = ts.JsDoc.getJsDocCommentsFromDeclarations(declarations, checker); if (checker && (doc.length === 0 || declarations.some(hasJSDocInheritDocTag))) { var seenSymbols_2 = new ts.Set(); var _loop_23 = function (declaration) { var inheritedDocs = findBaseOfDeclaration(checker, declaration, function (symbol) { if (!seenSymbols_2.has(symbol)) { seenSymbols_2.add(symbol); if (declaration.kind === 172 /* SyntaxKind.GetAccessor */ || declaration.kind === 173 /* SyntaxKind.SetAccessor */) { return symbol.getContextualDocumentationComment(declaration, checker); } return symbol.getDocumentationComment(checker); } }); // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(ts.lineBreakPart(), doc); }; for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { var declaration = declarations_7[_i]; _loop_23(declaration); } } return doc; } function findBaseOfDeclaration(checker, declaration, cb) { var _a; if (ts.hasStaticModifier(declaration)) return; var classOrInterfaceDeclaration = ((_a = declaration.parent) === null || _a === void 0 ? void 0 : _a.kind) === 171 /* SyntaxKind.Constructor */ ? declaration.parent.parent : declaration.parent; if (!classOrInterfaceDeclaration) return; return ts.firstDefined(ts.getAllSuperTypeNodes(classOrInterfaceDeclaration), function (superTypeNode) { var symbol = checker.getPropertyOfType(checker.getTypeAtLocation(superTypeNode), declaration.symbol.name); return symbol ? cb(symbol) : undefined; }); } var SourceFileObject = /** @class */ (function (_super) { __extends(SourceFileObject, _super); function SourceFileObject(kind, pos, end) { var _this = _super.call(this, kind, pos, end) || this; _this.kind = 305 /* SyntaxKind.SourceFile */; return _this; } SourceFileObject.prototype.update = function (newText, textChangeRange) { return ts.updateSourceFile(this, newText, textChangeRange); }; SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) { return ts.getLineAndCharacterOfPosition(this, position); }; SourceFileObject.prototype.getLineStarts = function () { return ts.getLineStarts(this); }; SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character, allowEdits) { return ts.computePositionOfLineAndCharacter(ts.getLineStarts(this), line, character, this.text, allowEdits); }; SourceFileObject.prototype.getLineEndOfPosition = function (pos) { var line = this.getLineAndCharacterOfPosition(pos).line; var lineStarts = this.getLineStarts(); var lastCharPos; if (line + 1 >= lineStarts.length) { lastCharPos = this.getEnd(); } if (!lastCharPos) { lastCharPos = lineStarts[line + 1] - 1; } var fullText = this.getFullText(); // if the new line is "\r\n", we should return the last non-new-line-character position return fullText[lastCharPos] === "\n" && fullText[lastCharPos - 1] === "\r" ? lastCharPos - 1 : lastCharPos; }; SourceFileObject.prototype.getNamedDeclarations = function () { if (!this.namedDeclarations) { this.namedDeclarations = this.computeNamedDeclarations(); } return this.namedDeclarations; }; SourceFileObject.prototype.computeNamedDeclarations = function () { var result = ts.createMultiMap(); this.forEachChild(visit); return result; function addDeclaration(declaration) { var name = getDeclarationName(declaration); if (name) { result.add(name, declaration); } } function getDeclarations(name) { var declarations = result.get(name); if (!declarations) { result.set(name, declarations = []); } return declarations; } function getDeclarationName(declaration) { var name = ts.getNonAssignedNameOfDeclaration(declaration); return name && (ts.isComputedPropertyName(name) && ts.isPropertyAccessExpression(name.expression) ? name.expression.name.text : ts.isPropertyName(name) ? ts.getNameFromPropertyName(name) : undefined); } function visit(node) { switch (node.kind) { case 256 /* SyntaxKind.FunctionDeclaration */: case 213 /* SyntaxKind.FunctionExpression */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: var functionDeclaration = node; var declarationName = getDeclarationName(functionDeclaration); if (declarationName) { var declarations = getDeclarations(declarationName); var lastDeclaration = ts.lastOrUndefined(declarations); // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { // Overwrite the last declaration if it was an overload // and this one is an implementation. if (functionDeclaration.body && !lastDeclaration.body) { declarations[declarations.length - 1] = functionDeclaration; } } else { declarations.push(functionDeclaration); } } ts.forEachChild(node, visit); break; case 257 /* SyntaxKind.ClassDeclaration */: case 226 /* SyntaxKind.ClassExpression */: case 258 /* SyntaxKind.InterfaceDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 261 /* SyntaxKind.ModuleDeclaration */: case 265 /* SyntaxKind.ImportEqualsDeclaration */: case 275 /* SyntaxKind.ExportSpecifier */: case 270 /* SyntaxKind.ImportSpecifier */: case 267 /* SyntaxKind.ImportClause */: case 268 /* SyntaxKind.NamespaceImport */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: case 182 /* SyntaxKind.TypeLiteral */: addDeclaration(node); ts.forEachChild(node, visit); break; case 164 /* SyntaxKind.Parameter */: // Only consider parameter properties if (!ts.hasSyntacticModifier(node, 16476 /* ModifierFlags.ParameterPropertyModifier */)) { break; } // falls through case 254 /* SyntaxKind.VariableDeclaration */: case 203 /* SyntaxKind.BindingElement */: { var decl = node; if (ts.isBindingPattern(decl.name)) { ts.forEachChild(decl.name, visit); break; } if (decl.initializer) { visit(decl.initializer); } } // falls through case 299 /* SyntaxKind.EnumMember */: case 167 /* SyntaxKind.PropertyDeclaration */: case 166 /* SyntaxKind.PropertySignature */: addDeclaration(node); break; case 272 /* SyntaxKind.ExportDeclaration */: // Handle named exports case e.g.: // export {a, b as B} from "mod"; var exportDeclaration = node; if (exportDeclaration.exportClause) { if (ts.isNamedExports(exportDeclaration.exportClause)) { ts.forEach(exportDeclaration.exportClause.elements, visit); } else { visit(exportDeclaration.exportClause.name); } } break; case 266 /* SyntaxKind.ImportDeclaration */: var importClause = node.importClause; if (importClause) { // Handle default import case e.g.: // import d from "mod"; if (importClause.name) { addDeclaration(importClause.name); } // Handle named bindings in imports e.g.: // import * as NS from "mod"; // import {a, b as B} from "mod"; if (importClause.namedBindings) { if (importClause.namedBindings.kind === 268 /* SyntaxKind.NamespaceImport */) { addDeclaration(importClause.namedBindings); } else { ts.forEach(importClause.namedBindings.elements, visit); } } } break; case 221 /* SyntaxKind.BinaryExpression */: if (ts.getAssignmentDeclarationKind(node) !== 0 /* AssignmentDeclarationKind.None */) { addDeclaration(node); } // falls through default: ts.forEachChild(node, visit); } } }; return SourceFileObject; }(NodeObject)); var SourceMapSourceObject = /** @class */ (function () { function SourceMapSourceObject(fileName, text, skipTrivia) { this.fileName = fileName; this.text = text; this.skipTrivia = skipTrivia; } SourceMapSourceObject.prototype.getLineAndCharacterOfPosition = function (pos) { return ts.getLineAndCharacterOfPosition(this, pos); }; return SourceMapSourceObject; }()); function getServicesObjectAllocator() { return { getNodeConstructor: function () { return NodeObject; }, getTokenConstructor: function () { return TokenObject; }, getIdentifierConstructor: function () { return IdentifierObject; }, getPrivateIdentifierConstructor: function () { return PrivateIdentifierObject; }, getSourceFileConstructor: function () { return SourceFileObject; }, getSymbolConstructor: function () { return SymbolObject; }, getTypeConstructor: function () { return TypeObject; }, getSignatureConstructor: function () { return SignatureObject; }, getSourceMapSourceConstructor: function () { return SourceMapSourceObject; }, }; } function toEditorSettings(optionsAsMap) { var allPropertiesAreCamelCased = true; for (var key in optionsAsMap) { if (ts.hasProperty(optionsAsMap, key) && !isCamelCase(key)) { allPropertiesAreCamelCased = false; break; } } if (allPropertiesAreCamelCased) { return optionsAsMap; } var settings = {}; for (var key in optionsAsMap) { if (ts.hasProperty(optionsAsMap, key)) { var newKey = isCamelCase(key) ? key : key.charAt(0).toLowerCase() + key.substr(1); settings[newKey] = optionsAsMap[key]; } } return settings; } ts.toEditorSettings = toEditorSettings; function isCamelCase(s) { return !s.length || s.charAt(0) === s.charAt(0).toLowerCase(); } function displayPartsToString(displayParts) { if (displayParts) { return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join(""); } return ""; } ts.displayPartsToString = displayPartsToString; function getDefaultCompilerOptions() { // Always default to "ScriptTarget.ES5" for the language service return { target: 1 /* ScriptTarget.ES5 */, jsx: 1 /* JsxEmit.Preserve */ }; } ts.getDefaultCompilerOptions = getDefaultCompilerOptions; function getSupportedCodeFixes() { return ts.codefix.getSupportedErrorCodes(); } ts.getSupportedCodeFixes = getSupportedCodeFixes; // Cache host information about script Should be refreshed // at each language service public entry point, since we don't know when // the set of scripts handled by the host changes. var HostCache = /** @class */ (function () { function HostCache(host, getCanonicalFileName) { this.host = host; // script id => script index this.currentDirectory = host.getCurrentDirectory(); this.fileNameToEntry = new ts.Map(); // Initialize the list with the root file names var rootFileNames = host.getScriptFileNames(); ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "initializeHostCache", { count: rootFileNames.length }); for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) { var fileName = rootFileNames_1[_i]; this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName)); } ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop(); } HostCache.prototype.createEntry = function (fileName, path) { var entry; var scriptSnapshot = this.host.getScriptSnapshot(fileName); if (scriptSnapshot) { entry = { hostFileName: fileName, version: this.host.getScriptVersion(fileName), scriptSnapshot: scriptSnapshot, scriptKind: ts.getScriptKind(fileName, this.host) }; } else { entry = fileName; } this.fileNameToEntry.set(path, entry); return entry; }; HostCache.prototype.getEntryByPath = function (path) { return this.fileNameToEntry.get(path); }; HostCache.prototype.getHostFileInformation = function (path) { var entry = this.fileNameToEntry.get(path); return !ts.isString(entry) ? entry : undefined; }; HostCache.prototype.getOrCreateEntryByPath = function (fileName, path) { var info = this.getEntryByPath(path) || this.createEntry(fileName, path); return ts.isString(info) ? undefined : info; // TODO: GH#18217 }; HostCache.prototype.getRootFileNames = function () { var names = []; this.fileNameToEntry.forEach(function (entry) { if (ts.isString(entry)) { names.push(entry); } else { names.push(entry.hostFileName); } }); return names; }; HostCache.prototype.getScriptSnapshot = function (path) { var file = this.getHostFileInformation(path); return (file && file.scriptSnapshot); // TODO: GH#18217 }; return HostCache; }()); var SyntaxTreeCache = /** @class */ (function () { function SyntaxTreeCache(host) { this.host = host; } SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) { var _a, _b, _c, _d, _e, _f, _g, _h; var scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } var scriptKind = ts.getScriptKind(fileName, this.host); var version = this.host.getScriptVersion(fileName); var sourceFile; if (this.currentFileName !== fileName) { // This is a new file, just parse it var options = { languageVersion: 99 /* ScriptTarget.Latest */, impliedNodeFormat: ts.getImpliedNodeFormatForFile(ts.toPath(fileName, this.host.getCurrentDirectory(), ((_c = (_b = (_a = this.host).getCompilerHost) === null || _b === void 0 ? void 0 : _b.call(_a)) === null || _c === void 0 ? void 0 : _c.getCanonicalFileName) || ts.hostGetCanonicalFileName(this.host)), (_h = (_g = (_f = (_e = (_d = this.host).getCompilerHost) === null || _e === void 0 ? void 0 : _e.call(_d)) === null || _f === void 0 ? void 0 : _f.getModuleResolutionCache) === null || _g === void 0 ? void 0 : _g.call(_f)) === null || _h === void 0 ? void 0 : _h.getPackageJsonInfoCache(), this.host, this.host.getCompilationSettings()), setExternalModuleIndicator: ts.getSetExternalModuleIndicator(this.host.getCompilationSettings()) }; sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, options, version, /*setNodeParents*/ true, scriptKind); } else if (this.currentFileVersion !== version) { // This is the same file, just a newer version. Incrementally parse the file. var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot); sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange); } if (sourceFile) { // All done, ensure state is up to date this.currentFileVersion = version; this.currentFileName = fileName; this.currentFileScriptSnapshot = scriptSnapshot; this.currentSourceFile = sourceFile; } return this.currentSourceFile; }; return SyntaxTreeCache; }()); function setSourceFileFields(sourceFile, scriptSnapshot, version) { sourceFile.version = version; sourceFile.scriptSnapshot = scriptSnapshot; } function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTargetOrOptions, version, setNodeParents, scriptKind) { var sourceFile = ts.createSourceFile(fileName, ts.getSnapshotText(scriptSnapshot), scriptTargetOrOptions, setNodeParents, scriptKind); setSourceFileFields(sourceFile, scriptSnapshot, version); return sourceFile; } ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile; function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) { // If we were given a text change range, and our version or open-ness changed, then // incrementally parse this file. if (textChangeRange) { if (version !== sourceFile.version) { var newText = void 0; // grab the fragment from the beginning of the original text to the beginning of the span var prefix = textChangeRange.span.start !== 0 ? sourceFile.text.substr(0, textChangeRange.span.start) : ""; // grab the fragment from the end of the span till the end of the original text var suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span)) : ""; if (textChangeRange.newLength === 0) { // edit was a deletion - just combine prefix and suffix newText = prefix && suffix ? prefix + suffix : prefix || suffix; } else { // it was actual edit, fetch the fragment of new text that correspond to new span var changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength); // combine prefix, changed text and suffix newText = prefix && suffix ? prefix + changedText + suffix : prefix ? (prefix + changedText) : (changedText + suffix); } var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later newSourceFile.nameTable = undefined; // dispose all resources held by old script snapshot if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) { if (sourceFile.scriptSnapshot.dispose) { sourceFile.scriptSnapshot.dispose(); } sourceFile.scriptSnapshot = undefined; } return newSourceFile; } } var options = { languageVersion: sourceFile.languageVersion, impliedNodeFormat: sourceFile.impliedNodeFormat, setExternalModuleIndicator: sourceFile.setExternalModuleIndicator, }; // Otherwise, just create a new source file. return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, options, version, /*setNodeParents*/ true, sourceFile.scriptKind); } ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile; var NoopCancellationToken = { isCancellationRequested: ts.returnFalse, throwIfCancellationRequested: ts.noop, }; var CancellationTokenObject = /** @class */ (function () { function CancellationTokenObject(cancellationToken) { this.cancellationToken = cancellationToken; } CancellationTokenObject.prototype.isCancellationRequested = function () { return this.cancellationToken.isCancellationRequested(); }; CancellationTokenObject.prototype.throwIfCancellationRequested = function () { if (this.isCancellationRequested()) { ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "cancellationThrown", { kind: "CancellationTokenObject" }); throw new ts.OperationCanceledException(); } }; return CancellationTokenObject; }()); /* @internal */ /** A cancellation that throttles calls to the host */ var ThrottledCancellationToken = /** @class */ (function () { function ThrottledCancellationToken(hostCancellationToken, throttleWaitMilliseconds) { if (throttleWaitMilliseconds === void 0) { throttleWaitMilliseconds = 20; } this.hostCancellationToken = hostCancellationToken; this.throttleWaitMilliseconds = throttleWaitMilliseconds; // Store when we last tried to cancel. Checking cancellation can be expensive (as we have // to marshall over to the host layer). So we only bother actually checking once enough // time has passed. this.lastCancellationCheckTime = 0; } ThrottledCancellationToken.prototype.isCancellationRequested = function () { var time = ts.timestamp(); var duration = Math.abs(time - this.lastCancellationCheckTime); if (duration >= this.throttleWaitMilliseconds) { // Check no more than once every throttle wait milliseconds this.lastCancellationCheckTime = time; return this.hostCancellationToken.isCancellationRequested(); } return false; }; ThrottledCancellationToken.prototype.throwIfCancellationRequested = function () { if (this.isCancellationRequested()) { ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "cancellationThrown", { kind: "ThrottledCancellationToken" }); throw new ts.OperationCanceledException(); } }; return ThrottledCancellationToken; }()); ts.ThrottledCancellationToken = ThrottledCancellationToken; var invalidOperationsInPartialSemanticMode = [ "getSemanticDiagnostics", "getSuggestionDiagnostics", "getCompilerOptionsDiagnostics", "getSemanticClassifications", "getEncodedSemanticClassifications", "getCodeFixesAtPosition", "getCombinedCodeFix", "applyCodeActionCommand", "organizeImports", "getEditsForFileRename", "getEmitOutput", "getApplicableRefactors", "getEditsForRefactor", "prepareCallHierarchy", "provideCallHierarchyIncomingCalls", "provideCallHierarchyOutgoingCalls", "provideInlayHints" ]; var invalidOperationsInSyntacticMode = __spreadArray(__spreadArray([], invalidOperationsInPartialSemanticMode, true), [ "getCompletionsAtPosition", "getCompletionEntryDetails", "getCompletionEntrySymbol", "getSignatureHelpItems", "getQuickInfoAtPosition", "getDefinitionAtPosition", "getDefinitionAndBoundSpan", "getImplementationAtPosition", "getTypeDefinitionAtPosition", "getReferencesAtPosition", "findReferences", "getOccurrencesAtPosition", "getDocumentHighlights", "getNavigateToItems", "getRenameInfo", "findRenameLocations", "getApplicableRefactors", ], false); function createLanguageService(host, documentRegistry, syntaxOnlyOrLanguageServiceMode) { var _a; var _b; if (documentRegistry === void 0) { documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } var languageServiceMode; if (syntaxOnlyOrLanguageServiceMode === undefined) { languageServiceMode = ts.LanguageServiceMode.Semantic; } else if (typeof syntaxOnlyOrLanguageServiceMode === "boolean") { // languageServiceMode = SyntaxOnly languageServiceMode = syntaxOnlyOrLanguageServiceMode ? ts.LanguageServiceMode.Syntactic : ts.LanguageServiceMode.Semantic; } else { languageServiceMode = syntaxOnlyOrLanguageServiceMode; } var syntaxTreeCache = new SyntaxTreeCache(host); var program; var lastProjectVersion; var lastTypesRootVersion = 0; var cancellationToken = host.getCancellationToken ? new CancellationTokenObject(host.getCancellationToken()) : NoopCancellationToken; var currentDirectory = host.getCurrentDirectory(); // Checks if the localized messages json is set, and if not, query the host for it ts.maybeSetLocalizedDiagnosticMessages((_b = host.getLocalizedDiagnosticMessages) === null || _b === void 0 ? void 0 : _b.bind(host)); function log(message) { if (host.log) { host.log(message); } } var useCaseSensitiveFileNames = ts.hostUsesCaseSensitiveFileNames(host); var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); var sourceMapper = ts.getSourceMapper({ useCaseSensitiveFileNames: function () { return useCaseSensitiveFileNames; }, getCurrentDirectory: function () { return currentDirectory; }, getProgram: getProgram, fileExists: ts.maybeBind(host, host.fileExists), readFile: ts.maybeBind(host, host.readFile), getDocumentPositionMapper: ts.maybeBind(host, host.getDocumentPositionMapper), getSourceFileLike: ts.maybeBind(host, host.getSourceFileLike), log: log }); function getValidSourceFile(fileName) { var sourceFile = program.getSourceFile(fileName); if (!sourceFile) { var error = new Error("Could not find source file: '".concat(fileName, "'.")); // We've been having trouble debugging this, so attach sidecar data for the tsserver log. // See https://github.com/microsoft/TypeScript/issues/30180. error.ProgramFiles = program.getSourceFiles().map(function (f) { return f.fileName; }); throw error; } return sourceFile; } function synchronizeHostData() { var _a, _b, _c; ts.Debug.assert(languageServiceMode !== ts.LanguageServiceMode.Syntactic); // perform fast check if host supports it if (host.getProjectVersion) { var hostProjectVersion = host.getProjectVersion(); if (hostProjectVersion) { if (lastProjectVersion === hostProjectVersion && !((_a = host.hasChangedAutomaticTypeDirectiveNames) === null || _a === void 0 ? void 0 : _a.call(host))) { return; } lastProjectVersion = hostProjectVersion; } } var typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0; if (lastTypesRootVersion !== typeRootsVersion) { log("TypeRoots version has changed; provide new program"); program = undefined; // TODO: GH#18217 lastTypesRootVersion = typeRootsVersion; } // Get a fresh cache of the host information var hostCache = new HostCache(host, getCanonicalFileName); var rootFileNames = hostCache.getRootFileNames(); var newSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); var hasInvalidatedResolution = host.hasInvalidatedResolution || ts.returnFalse; var hasChangedAutomaticTypeDirectiveNames = ts.maybeBind(host, host.hasChangedAutomaticTypeDirectiveNames); var projectReferences = (_b = host.getProjectReferences) === null || _b === void 0 ? void 0 : _b.call(host); var parsedCommandLines; var parseConfigHost = { useCaseSensitiveFileNames: useCaseSensitiveFileNames, fileExists: fileExists, readFile: readFile, readDirectory: readDirectory, trace: ts.maybeBind(host, host.trace), getCurrentDirectory: function () { return currentDirectory; }, onUnRecoverableConfigFileDiagnostic: ts.noop, }; // If the program is already up-to-date, we can reuse it if (ts.isProgramUptoDate(program, rootFileNames, newSettings, function (_path, fileName) { return host.getScriptVersion(fileName); }, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { return; } // IMPORTANT - It is critical from this moment onward that we do not check // cancellation tokens. We are about to mutate source files from a previous program // instance. If we cancel midway through, we may end up in an inconsistent state where // the program points to old source files that have been invalidated because of // incremental parsing. // Now create a new compiler var compilerHost = { getSourceFile: getOrCreateSourceFile, getSourceFileByPath: getOrCreateSourceFileByPath, getCancellationToken: function () { return cancellationToken; }, getCanonicalFileName: getCanonicalFileName, useCaseSensitiveFileNames: function () { return useCaseSensitiveFileNames; }, getNewLine: function () { return ts.getNewLineCharacter(newSettings, function () { return ts.getNewLineOrDefaultFromHost(host); }); }, getDefaultLibFileName: function (options) { return host.getDefaultLibFileName(options); }, writeFile: ts.noop, getCurrentDirectory: function () { return currentDirectory; }, fileExists: fileExists, readFile: readFile, getSymlinkCache: ts.maybeBind(host, host.getSymlinkCache), realpath: ts.maybeBind(host, host.realpath), directoryExists: function (directoryName) { return ts.directoryProbablyExists(directoryName, host); }, getDirectories: function (path) { return host.getDirectories ? host.getDirectories(path) : []; }, readDirectory: readDirectory, onReleaseOldSourceFile: onReleaseOldSourceFile, onReleaseParsedCommandLine: onReleaseParsedCommandLine, hasInvalidatedResolution: hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames: hasChangedAutomaticTypeDirectiveNames, trace: parseConfigHost.trace, resolveModuleNames: ts.maybeBind(host, host.resolveModuleNames), getModuleResolutionCache: ts.maybeBind(host, host.getModuleResolutionCache), resolveTypeReferenceDirectives: ts.maybeBind(host, host.resolveTypeReferenceDirectives), useSourceOfProjectReferenceRedirect: ts.maybeBind(host, host.useSourceOfProjectReferenceRedirect), getParsedCommandLine: getParsedCommandLine, }; (_c = host.setCompilerHost) === null || _c === void 0 ? void 0 : _c.call(host, compilerHost); var documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings); var options = { rootNames: rootFileNames, options: newSettings, host: compilerHost, oldProgram: program, projectReferences: projectReferences }; program = ts.createProgram(options); // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. // It needs to be cleared to allow all collected snapshots to be released hostCache = undefined; parsedCommandLines = undefined; // We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above, // Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during // the course of whatever called `synchronizeHostData` sourceMapper.clearCache(); // Make sure all the nodes in the program are both bound, and have their parent // pointers set property. program.getTypeChecker(); return; function getParsedCommandLine(fileName) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var existing = parsedCommandLines === null || parsedCommandLines === void 0 ? void 0 : parsedCommandLines.get(path); if (existing !== undefined) return existing || undefined; var result = host.getParsedCommandLine ? host.getParsedCommandLine(fileName) : getParsedCommandLineOfConfigFileUsingSourceFile(fileName); (parsedCommandLines || (parsedCommandLines = new ts.Map())).set(path, result || false); return result; } function getParsedCommandLineOfConfigFileUsingSourceFile(configFileName) { var result = getOrCreateSourceFile(configFileName, 100 /* ScriptTarget.JSON */); if (!result) return undefined; result.path = ts.toPath(configFileName, currentDirectory, getCanonicalFileName); result.resolvedPath = result.path; result.originalFileName = result.fileName; return ts.parseJsonSourceFileConfigFileContent(result, parseConfigHost, ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), currentDirectory), /*optionsToExtend*/ undefined, ts.getNormalizedAbsolutePath(configFileName, currentDirectory)); } function onReleaseParsedCommandLine(configFileName, oldResolvedRef, oldOptions) { var _a; if (host.getParsedCommandLine) { (_a = host.onReleaseParsedCommandLine) === null || _a === void 0 ? void 0 : _a.call(host, configFileName, oldResolvedRef, oldOptions); } else if (oldResolvedRef) { onReleaseOldSourceFile(oldResolvedRef.sourceFile, oldOptions); } } function fileExists(fileName) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var entry = hostCache && hostCache.getEntryByPath(path); return entry ? !ts.isString(entry) : (!!host.fileExists && host.fileExists(fileName)); } function readFile(fileName) { // stub missing host functionality var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); var entry = hostCache && hostCache.getEntryByPath(path); if (entry) { return ts.isString(entry) ? undefined : ts.getSnapshotText(entry.scriptSnapshot); } return host.readFile && host.readFile(fileName); } function readDirectory(path, extensions, exclude, include, depth) { ts.Debug.checkDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'"); return host.readDirectory(path, extensions, exclude, include, depth); } // Release any files we have acquired in the old program but are // not part of the new program. function onReleaseOldSourceFile(oldSourceFile, oldOptions) { var oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions); documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, oldSettingsKey, oldSourceFile.scriptKind); } function getOrCreateSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) { return getOrCreateSourceFileByPath(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), languageVersion, onError, shouldCreateNewSourceFile); } function getOrCreateSourceFileByPath(fileName, path, _languageVersion, _onError, shouldCreateNewSourceFile) { ts.Debug.assert(hostCache !== undefined, "getOrCreateSourceFileByPath called after typical CompilerHost lifetime, check the callstack something with a reference to an old host."); // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined // to the program to allow reporting of errors for missing files. var hostFileInformation = hostCache && hostCache.getOrCreateEntryByPath(fileName, path); if (!hostFileInformation) { return undefined; } // Check if the language version has changed since we last created a program; if they are the same, // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile // can not be reused. we have to dump all syntax trees and create new ones. if (!shouldCreateNewSourceFile) { // Check if the old program had this file already var oldSourceFile = program && program.getSourceFileByPath(path); if (oldSourceFile) { // We already had a source file for this file name. Go to the registry to // ensure that we get the right up to date version of it. We need this to // address the following race-condition. Specifically, say we have the following: // // LS1 // \ // DocumentRegistry // / // LS2 // // Each LS has a reference to file 'foo.ts' at version 1. LS2 then updates // it's version of 'foo.ts' to version 2. This will cause LS2 and the // DocumentRegistry to have version 2 of the document. However, LS1 will // have version 1. And *importantly* this source file will be *corrupt*. // The act of creating version 2 of the file irrevocably damages the version // 1 file. // // So, later when we call into LS1, we need to make sure that it doesn't use // it's source file any more, and instead defers to DocumentRegistry to get // either version 1, version 2 (or some other version) depending on what the // host says should be used. // We do not support the scenario where a host can modify a registered // file's script kind, i.e. in one project some file is treated as ".ts" // and in another as ".js" if (hostFileInformation.scriptKind === oldSourceFile.scriptKind) { return documentRegistry.updateDocumentWithKey(fileName, path, host, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } else { // Release old source file and fall through to aquire new file with new script kind documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, documentRegistry.getKeyForCompilationSettings(program.getCompilerOptions()), oldSourceFile.scriptKind); } } // We didn't already have the file. Fall through and acquire it from the registry. } // Could not find this file in the old program, create a new SourceFile for it. return documentRegistry.acquireDocumentWithKey(fileName, path, host, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind); } } // TODO: GH#18217 frequently asserted as defined function getProgram() { if (languageServiceMode === ts.LanguageServiceMode.Syntactic) { ts.Debug.assert(program === undefined); return undefined; } synchronizeHostData(); return program; } function getAutoImportProvider() { var _a; return (_a = host.getPackageJsonAutoImportProvider) === null || _a === void 0 ? void 0 : _a.call(host); } function cleanupSemanticCache() { program = undefined; // TODO: GH#18217 } function dispose() { if (program) { // Use paths to ensure we are using correct key and paths as document registry could be created with different current directory than host var key_1 = documentRegistry.getKeyForCompilationSettings(program.getCompilerOptions()); ts.forEach(program.getSourceFiles(), function (f) { return documentRegistry.releaseDocumentWithKey(f.resolvedPath, key_1, f.scriptKind); }); program = undefined; // TODO: GH#18217 } host = undefined; } /// Diagnostics function getSyntacticDiagnostics(fileName) { synchronizeHostData(); return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken).slice(); } /** * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors * If '-d' enabled, report both semantic and emitter errors */ function getSemanticDiagnostics(fileName) { synchronizeHostData(); var targetSourceFile = getValidSourceFile(fileName); // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file. // Therefore only get diagnostics for given file. var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); if (!ts.getEmitDeclarations(program.getCompilerOptions())) { return semanticDiagnostics.slice(); } // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken); return __spreadArray(__spreadArray([], semanticDiagnostics, true), declarationDiagnostics, true); } function getSuggestionDiagnostics(fileName) { synchronizeHostData(); return ts.computeSuggestionDiagnostics(getValidSourceFile(fileName), program, cancellationToken); } function getCompilerOptionsDiagnostics() { synchronizeHostData(); return __spreadArray(__spreadArray([], program.getOptionsDiagnostics(cancellationToken), true), program.getGlobalDiagnostics(cancellationToken), true); } function getCompletionsAtPosition(fileName, position, options, formattingSettings) { if (options === void 0) { options = ts.emptyOptions; } // Convert from deprecated options names to new names var fullPreferences = __assign(__assign({}, ts.identity(options)), { includeCompletionsForModuleExports: options.includeCompletionsForModuleExports || options.includeExternalModuleExports, includeCompletionsWithInsertText: options.includeCompletionsWithInsertText || options.includeInsertTextCompletions }); synchronizeHostData(); return ts.Completions.getCompletionsAtPosition(host, program, log, getValidSourceFile(fileName), position, fullPreferences, options.triggerCharacter, options.triggerKind, cancellationToken, formattingSettings && ts.formatting.getFormatContext(formattingSettings, host)); } function getCompletionEntryDetails(fileName, position, name, formattingOptions, source, preferences, data) { if (preferences === void 0) { preferences = ts.emptyOptions; } synchronizeHostData(); return ts.Completions.getCompletionEntryDetails(program, log, getValidSourceFile(fileName), position, { name: name, source: source, data: data }, host, (formattingOptions && ts.formatting.getFormatContext(formattingOptions, host)), // TODO: GH#18217 preferences, cancellationToken); } function getCompletionEntrySymbol(fileName, position, name, source, preferences) { if (preferences === void 0) { preferences = ts.emptyOptions; } synchronizeHostData(); return ts.Completions.getCompletionEntrySymbol(program, log, getValidSourceFile(fileName), position, { name: name, source: source }, host, preferences); } function getQuickInfoAtPosition(fileName, position) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var node = ts.getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { // Avoid giving quickInfo for the sourceFile as a whole. return undefined; } var typeChecker = program.getTypeChecker(); var nodeForQuickInfo = getNodeForQuickInfo(node); var symbol = getSymbolAtLocationForQuickInfo(nodeForQuickInfo, typeChecker); if (!symbol || typeChecker.isUnknownSymbol(symbol)) { var type_2 = shouldGetType(sourceFile, nodeForQuickInfo, position) ? typeChecker.getTypeAtLocation(nodeForQuickInfo) : undefined; return type_2 && { kind: "" /* ScriptElementKind.unknown */, kindModifiers: "" /* ScriptElementKindModifier.none */, textSpan: ts.createTextSpanFromNode(nodeForQuickInfo, sourceFile), displayParts: typeChecker.runWithCancellationToken(cancellationToken, function (typeChecker) { return ts.typeToDisplayParts(typeChecker, type_2, ts.getContainerNode(nodeForQuickInfo)); }), documentation: type_2.symbol ? type_2.symbol.getDocumentationComment(typeChecker) : undefined, tags: type_2.symbol ? type_2.symbol.getJsDocTags(typeChecker) : undefined }; } var _a = typeChecker.runWithCancellationToken(cancellationToken, function (typeChecker) { return ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, ts.getContainerNode(nodeForQuickInfo), nodeForQuickInfo); }), symbolKind = _a.symbolKind, displayParts = _a.displayParts, documentation = _a.documentation, tags = _a.tags; return { kind: symbolKind, kindModifiers: ts.SymbolDisplay.getSymbolModifiers(typeChecker, symbol), textSpan: ts.createTextSpanFromNode(nodeForQuickInfo, sourceFile), displayParts: displayParts, documentation: documentation, tags: tags, }; } function getNodeForQuickInfo(node) { if (ts.isNewExpression(node.parent) && node.pos === node.parent.pos) { return node.parent.expression; } if (ts.isNamedTupleMember(node.parent) && node.pos === node.parent.pos) { return node.parent; } if (ts.isImportMeta(node.parent) && node.parent.name === node) { return node.parent; } return node; } function shouldGetType(sourceFile, node, position) { switch (node.kind) { case 79 /* SyntaxKind.Identifier */: return !ts.isLabelName(node) && !ts.isTagName(node) && !ts.isConstTypeReference(node.parent); case 206 /* SyntaxKind.PropertyAccessExpression */: case 161 /* SyntaxKind.QualifiedName */: // Don't return quickInfo if inside the comment in `a/**/.b` return !ts.isInComment(sourceFile, position); case 108 /* SyntaxKind.ThisKeyword */: case 192 /* SyntaxKind.ThisType */: case 106 /* SyntaxKind.SuperKeyword */: case 197 /* SyntaxKind.NamedTupleMember */: return true; case 231 /* SyntaxKind.MetaProperty */: return ts.isImportMeta(node); default: return false; } } /// Goto definition function getDefinitionAtPosition(fileName, position, searchOtherFilesOnly, stopAtAlias) { synchronizeHostData(); return ts.GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position, searchOtherFilesOnly, stopAtAlias); } function getDefinitionAndBoundSpan(fileName, position) { synchronizeHostData(); return ts.GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position); } function getTypeDefinitionAtPosition(fileName, position) { synchronizeHostData(); return ts.GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position); } /// Goto implementation function getImplementationAtPosition(fileName, position) { synchronizeHostData(); return ts.FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); } /// References and Occurrences function getOccurrencesAtPosition(fileName, position) { return ts.flatMap(getDocumentHighlights(fileName, position, [fileName]), function (entry) { return entry.highlightSpans.map(function (highlightSpan) { return (__assign(__assign({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, isWriteAccess: highlightSpan.kind === "writtenReference" /* HighlightSpanKind.writtenReference */ }, highlightSpan.isInString && { isInString: true }), highlightSpan.contextSpan && { contextSpan: highlightSpan.contextSpan })); }); }); } function getDocumentHighlights(fileName, position, filesToSearch) { var normalizedFileName = ts.normalizePath(fileName); ts.Debug.assert(filesToSearch.some(function (f) { return ts.normalizePath(f) === normalizedFileName; })); synchronizeHostData(); var sourceFilesToSearch = ts.mapDefined(filesToSearch, function (fileName) { return program.getSourceFile(fileName); }); var sourceFile = getValidSourceFile(fileName); return ts.DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch); } function findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var node = ts.getAdjustedRenameLocation(ts.getTouchingPropertyName(sourceFile, position)); if (!ts.Rename.nodeIsEligibleForRename(node)) return undefined; if (ts.isIdentifier(node) && (ts.isJsxOpeningElement(node.parent) || ts.isJsxClosingElement(node.parent)) && ts.isIntrinsicJsxName(node.escapedText)) { var _a = node.parent.parent, openingElement = _a.openingElement, closingElement = _a.closingElement; return [openingElement, closingElement].map(function (node) { var textSpan = ts.createTextSpanFromNode(node.tagName, sourceFile); return __assign({ fileName: sourceFile.fileName, textSpan: textSpan }, ts.FindAllReferences.toContextSpan(textSpan, sourceFile, node.parent)); }); } else { return getReferencesWorker(node, position, { findInStrings: findInStrings, findInComments: findInComments, providePrefixAndSuffixTextForRename: providePrefixAndSuffixTextForRename, use: 2 /* FindAllReferences.FindReferencesUse.Rename */ }, function (entry, originalNode, checker) { return ts.FindAllReferences.toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixTextForRename || false); }); } } function getReferencesAtPosition(fileName, position) { synchronizeHostData(); return getReferencesWorker(ts.getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: 1 /* FindAllReferences.FindReferencesUse.References */ }, ts.FindAllReferences.toReferenceEntry); } function getReferencesWorker(node, position, options, cb) { synchronizeHostData(); // Exclude default library when renaming as commonly user don't want to change that file. var sourceFiles = options && options.use === 2 /* FindAllReferences.FindReferencesUse.Rename */ ? program.getSourceFiles().filter(function (sourceFile) { return !program.isSourceFileDefaultLibrary(sourceFile); }) : program.getSourceFiles(); return ts.FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, cb); } function findReferences(fileName, position) { synchronizeHostData(); return ts.FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); } function getFileReferences(fileName) { synchronizeHostData(); return ts.FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(ts.FindAllReferences.toReferenceEntry); } function getNavigateToItems(searchValue, maxResultCount, fileName, excludeDtsFiles) { if (excludeDtsFiles === void 0) { excludeDtsFiles = false; } synchronizeHostData(); var sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles(); return ts.NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); } function getEmitOutput(fileName, emitOnlyDtsFiles, forceDtsEmit) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var customTransformers = host.getCustomTransformers && host.getCustomTransformers(); return ts.getFileEmitOutput(program, sourceFile, !!emitOnlyDtsFiles, cancellationToken, customTransformers, forceDtsEmit); } // Signature help /** * This is a semantic operation. */ function getSignatureHelpItems(fileName, position, _a) { var _b = _a === void 0 ? ts.emptyOptions : _a, triggerReason = _b.triggerReason; synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); return ts.SignatureHelp.getSignatureHelpItems(program, sourceFile, position, triggerReason, cancellationToken); } /// Syntactic features function getNonBoundSourceFile(fileName) { return syntaxTreeCache.getCurrentSourceFile(fileName); } function getNameOrDottedNameSpan(fileName, startPos, _endPos) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location var node = ts.getTouchingPropertyName(sourceFile, startPos); if (node === sourceFile) { return undefined; } switch (node.kind) { case 206 /* SyntaxKind.PropertyAccessExpression */: case 161 /* SyntaxKind.QualifiedName */: case 10 /* SyntaxKind.StringLiteral */: case 95 /* SyntaxKind.FalseKeyword */: case 110 /* SyntaxKind.TrueKeyword */: case 104 /* SyntaxKind.NullKeyword */: case 106 /* SyntaxKind.SuperKeyword */: case 108 /* SyntaxKind.ThisKeyword */: case 192 /* SyntaxKind.ThisType */: case 79 /* SyntaxKind.Identifier */: break; // Cant create the text span default: return undefined; } var nodeForStartPos = node; while (true) { if (ts.isRightSideOfPropertyAccess(nodeForStartPos) || ts.isRightSideOfQualifiedName(nodeForStartPos)) { // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node nodeForStartPos = nodeForStartPos.parent; } else if (ts.isNameOfModuleDeclaration(nodeForStartPos)) { // If this is name of a module declarations, check if this is right side of dotted module name // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of // Then this name is name from dotted module if (nodeForStartPos.parent.parent.kind === 261 /* SyntaxKind.ModuleDeclaration */ && nodeForStartPos.parent.parent.body === nodeForStartPos.parent) { // Use parent module declarations name for start pos nodeForStartPos = nodeForStartPos.parent.parent.name; } else { // We have to use this name for start pos break; } } else { // Is not a member expression so we have found the node for start pos break; } } return ts.createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd()); } function getBreakpointStatementAtPosition(fileName, position) { // doesn't use compiler - no need to synchronize with host var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return ts.BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } function getNavigationBarItems(fileName) { return ts.NavigationBar.getNavigationBarItems(syntaxTreeCache.getCurrentSourceFile(fileName), cancellationToken); } function getNavigationTree(fileName) { return ts.NavigationBar.getNavigationTree(syntaxTreeCache.getCurrentSourceFile(fileName), cancellationToken); } function getSemanticClassifications(fileName, span, format) { synchronizeHostData(); var responseFormat = format || "original" /* SemanticClassificationFormat.Original */; if (responseFormat === "2020" /* SemanticClassificationFormat.TwentyTwenty */) { return ts.classifier.v2020.getSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span); } else { return ts.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } } function getEncodedSemanticClassifications(fileName, span, format) { synchronizeHostData(); var responseFormat = format || "original" /* SemanticClassificationFormat.Original */; if (responseFormat === "original" /* SemanticClassificationFormat.Original */) { return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } else { return ts.classifier.v2020.getEncodedSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span); } } function getSyntacticClassifications(fileName, span) { // doesn't use compiler - no need to synchronize with host return ts.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getEncodedSyntacticClassifications(fileName, span) { // doesn't use compiler - no need to synchronize with host return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } function getOutliningSpans(fileName) { // doesn't use compiler - no need to synchronize with host var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return ts.OutliningElementsCollector.collectElements(sourceFile, cancellationToken); } var braceMatching = new ts.Map(ts.getEntries((_a = {}, _a[18 /* SyntaxKind.OpenBraceToken */] = 19 /* SyntaxKind.CloseBraceToken */, _a[20 /* SyntaxKind.OpenParenToken */] = 21 /* SyntaxKind.CloseParenToken */, _a[22 /* SyntaxKind.OpenBracketToken */] = 23 /* SyntaxKind.CloseBracketToken */, _a[31 /* SyntaxKind.GreaterThanToken */] = 29 /* SyntaxKind.LessThanToken */, _a))); braceMatching.forEach(function (value, key) { return braceMatching.set(value.toString(), Number(key)); }); function getBraceMatchingAtPosition(fileName, position) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var token = ts.getTouchingToken(sourceFile, position); var matchKind = token.getStart(sourceFile) === position ? braceMatching.get(token.kind.toString()) : undefined; var match = matchKind && ts.findChildOfKind(token.parent, matchKind, sourceFile); // We want to order the braces when we return the result. return match ? [ts.createTextSpanFromNode(token, sourceFile), ts.createTextSpanFromNode(match, sourceFile)].sort(function (a, b) { return a.start - b.start; }) : ts.emptyArray; } function getIndentationAtPosition(fileName, position, editorOptions) { var start = ts.timestamp(); var settings = toEditorSettings(editorOptions); var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); log("getIndentationAtPosition: getCurrentSourceFile: " + (ts.timestamp() - start)); start = ts.timestamp(); var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, settings); log("getIndentationAtPosition: computeIndentation : " + (ts.timestamp() - start)); return result; } function getFormattingEditsForRange(fileName, start, end, options) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); return ts.formatting.formatSelection(start, end, sourceFile, ts.formatting.getFormatContext(toEditorSettings(options), host)); } function getFormattingEditsForDocument(fileName, options) { return ts.formatting.formatDocument(syntaxTreeCache.getCurrentSourceFile(fileName), ts.formatting.getFormatContext(toEditorSettings(options), host)); } function getFormattingEditsAfterKeystroke(fileName, position, key, options) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var formatContext = ts.formatting.getFormatContext(toEditorSettings(options), host); if (!ts.isInComment(sourceFile, position)) { switch (key) { case "{": return ts.formatting.formatOnOpeningCurly(position, sourceFile, formatContext); case "}": return ts.formatting.formatOnClosingCurly(position, sourceFile, formatContext); case ";": return ts.formatting.formatOnSemicolon(position, sourceFile, formatContext); case "\n": return ts.formatting.formatOnEnter(position, sourceFile, formatContext); } } return []; } function getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences) { if (preferences === void 0) { preferences = ts.emptyOptions; } synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var span = ts.createTextSpanFromBounds(start, end); var formatContext = ts.formatting.getFormatContext(formatOptions, host); return ts.flatMap(ts.deduplicate(errorCodes, ts.equateValues, ts.compareValues), function (errorCode) { cancellationToken.throwIfCancellationRequested(); return ts.codefix.getFixes({ errorCode: errorCode, sourceFile: sourceFile, span: span, program: program, host: host, cancellationToken: cancellationToken, formatContext: formatContext, preferences: preferences }); }); } function getCombinedCodeFix(scope, fixId, formatOptions, preferences) { if (preferences === void 0) { preferences = ts.emptyOptions; } synchronizeHostData(); ts.Debug.assert(scope.type === "file"); var sourceFile = getValidSourceFile(scope.fileName); var formatContext = ts.formatting.getFormatContext(formatOptions, host); return ts.codefix.getAllFixes({ fixId: fixId, sourceFile: sourceFile, program: program, host: host, cancellationToken: cancellationToken, formatContext: formatContext, preferences: preferences }); } function organizeImports(args, formatOptions, preferences) { if (preferences === void 0) { preferences = ts.emptyOptions; } synchronizeHostData(); ts.Debug.assert(args.type === "file"); var sourceFile = getValidSourceFile(args.fileName); var formatContext = ts.formatting.getFormatContext(formatOptions, host); return ts.OrganizeImports.organizeImports(sourceFile, formatContext, host, program, preferences, args.skipDestructiveCodeActions); } function getEditsForFileRename(oldFilePath, newFilePath, formatOptions, preferences) { if (preferences === void 0) { preferences = ts.emptyOptions; } return ts.getEditsForFileRename(getProgram(), oldFilePath, newFilePath, host, ts.formatting.getFormatContext(formatOptions, host), preferences, sourceMapper); } function applyCodeActionCommand(fileName, actionOrFormatSettingsOrUndefined) { var action = typeof fileName === "string" ? actionOrFormatSettingsOrUndefined : fileName; return ts.isArray(action) ? Promise.all(action.map(function (a) { return applySingleCodeActionCommand(a); })) : applySingleCodeActionCommand(action); } function applySingleCodeActionCommand(action) { var getPath = function (path) { return ts.toPath(path, currentDirectory, getCanonicalFileName); }; ts.Debug.assertEqual(action.type, "install package"); return host.installPackage ? host.installPackage({ fileName: getPath(action.file), packageName: action.packageName }) : Promise.reject("Host does not implement `installPackage`"); } function getDocCommentTemplateAtPosition(fileName, position, options) { return ts.JsDoc.getDocCommentTemplateAtPosition(ts.getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position, options); } function isValidBraceCompletionAtPosition(fileName, position, openingBrace) { // '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too // expensive to do during typing scenarios // i.e. whether we're dealing with: // var x = new foo<| ( with class foo{} ) // or // var y = 3 <| if (openingBrace === 60 /* CharacterCodes.lessThan */) { return false; } var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Check if in a context where we don't want to perform any insertion if (ts.isInString(sourceFile, position)) { return false; } if (ts.isInsideJsxElementOrAttribute(sourceFile, position)) { return openingBrace === 123 /* CharacterCodes.openBrace */; } if (ts.isInTemplateString(sourceFile, position)) { return false; } switch (openingBrace) { case 39 /* CharacterCodes.singleQuote */: case 34 /* CharacterCodes.doubleQuote */: case 96 /* CharacterCodes.backtick */: return !ts.isInComment(sourceFile, position); } return true; } function getJsxClosingTagAtPosition(fileName, position) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var token = ts.findPrecedingToken(position, sourceFile); if (!token) return undefined; var element = token.kind === 31 /* SyntaxKind.GreaterThanToken */ && ts.isJsxOpeningElement(token.parent) ? token.parent.parent : ts.isJsxText(token) && ts.isJsxElement(token.parent) ? token.parent : undefined; if (element && isUnclosedTag(element)) { return { newText: "") }; } var fragment = token.kind === 31 /* SyntaxKind.GreaterThanToken */ && ts.isJsxOpeningFragment(token.parent) ? token.parent.parent : ts.isJsxText(token) && ts.isJsxFragment(token.parent) ? token.parent : undefined; if (fragment && isUnclosedFragment(fragment)) { return { newText: "" }; } } function getLinesForRange(sourceFile, textRange) { return { lineStarts: sourceFile.getLineStarts(), firstLine: sourceFile.getLineAndCharacterOfPosition(textRange.pos).line, lastLine: sourceFile.getLineAndCharacterOfPosition(textRange.end).line }; } function toggleLineComment(fileName, textRange, insertComment) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var textChanges = []; var _a = getLinesForRange(sourceFile, textRange), lineStarts = _a.lineStarts, firstLine = _a.firstLine, lastLine = _a.lastLine; var isCommenting = insertComment || false; var leftMostPosition = Number.MAX_VALUE; var lineTextStarts = new ts.Map(); var firstNonWhitespaceCharacterRegex = new RegExp(/\S/); var isJsx = ts.isInsideJsxElement(sourceFile, lineStarts[firstLine]); var openComment = isJsx ? "{/*" : "//"; // Check each line before any text changes. for (var i = firstLine; i <= lastLine; i++) { var lineText = sourceFile.text.substring(lineStarts[i], sourceFile.getLineEndOfPosition(lineStarts[i])); // Find the start of text and the left-most character. No-op on empty lines. var regExec = firstNonWhitespaceCharacterRegex.exec(lineText); if (regExec) { leftMostPosition = Math.min(leftMostPosition, regExec.index); lineTextStarts.set(i.toString(), regExec.index); if (lineText.substr(regExec.index, openComment.length) !== openComment) { isCommenting = insertComment === undefined || insertComment; } } } // Push all text changes. for (var i = firstLine; i <= lastLine; i++) { // If the range is multiline and ends on a beginning of a line, don't comment/uncomment. if (firstLine !== lastLine && lineStarts[i] === textRange.end) { continue; } var lineTextStart = lineTextStarts.get(i.toString()); // If the line is not an empty line; otherwise no-op. if (lineTextStart !== undefined) { if (isJsx) { textChanges.push.apply(textChanges, toggleMultilineComment(fileName, { pos: lineStarts[i] + leftMostPosition, end: sourceFile.getLineEndOfPosition(lineStarts[i]) }, isCommenting, isJsx)); } else if (isCommenting) { textChanges.push({ newText: openComment, span: { length: 0, start: lineStarts[i] + leftMostPosition } }); } else if (sourceFile.text.substr(lineStarts[i] + lineTextStart, openComment.length) === openComment) { textChanges.push({ newText: "", span: { length: openComment.length, start: lineStarts[i] + lineTextStart } }); } } } return textChanges; } function toggleMultilineComment(fileName, textRange, insertComment, isInsideJsx) { var _a; var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var textChanges = []; var text = sourceFile.text; var hasComment = false; var isCommenting = insertComment || false; var positions = []; var pos = textRange.pos; var isJsx = isInsideJsx !== undefined ? isInsideJsx : ts.isInsideJsxElement(sourceFile, pos); var openMultiline = isJsx ? "{/*" : "/*"; var closeMultiline = isJsx ? "*/}" : "*/"; var openMultilineRegex = isJsx ? "\\{\\/\\*" : "\\/\\*"; var closeMultilineRegex = isJsx ? "\\*\\/\\}" : "\\*\\/"; // Get all comment positions while (pos <= textRange.end) { // Start of comment is considered inside comment. var offset = text.substr(pos, openMultiline.length) === openMultiline ? openMultiline.length : 0; var commentRange = ts.isInComment(sourceFile, pos + offset); // If position is in a comment add it to the positions array. if (commentRange) { // Comment range doesn't include the brace character. Increase it to include them. if (isJsx) { commentRange.pos--; commentRange.end++; } positions.push(commentRange.pos); if (commentRange.kind === 3 /* SyntaxKind.MultiLineCommentTrivia */) { positions.push(commentRange.end); } hasComment = true; pos = commentRange.end + 1; } else { // If it's not in a comment range, then we need to comment the uncommented portions. var newPos = text.substring(pos, textRange.end).search("(".concat(openMultilineRegex, ")|(").concat(closeMultilineRegex, ")")); isCommenting = insertComment !== undefined ? insertComment : isCommenting || !ts.isTextWhiteSpaceLike(text, pos, newPos === -1 ? textRange.end : pos + newPos); // If isCommenting is already true we don't need to check whitespace again. pos = newPos === -1 ? textRange.end + 1 : pos + newPos + closeMultiline.length; } } // If it didn't found a comment and isCommenting is false means is only empty space. // We want to insert comment in this scenario. if (isCommenting || !hasComment) { if (((_a = ts.isInComment(sourceFile, textRange.pos)) === null || _a === void 0 ? void 0 : _a.kind) !== 2 /* SyntaxKind.SingleLineCommentTrivia */) { ts.insertSorted(positions, textRange.pos, ts.compareValues); } ts.insertSorted(positions, textRange.end, ts.compareValues); // Insert open comment if the first position is not a comment already. var firstPos = positions[0]; if (text.substr(firstPos, openMultiline.length) !== openMultiline) { textChanges.push({ newText: openMultiline, span: { length: 0, start: firstPos } }); } // Insert open and close comment to all positions between first and last. Exclusive. for (var i = 1; i < positions.length - 1; i++) { if (text.substr(positions[i] - closeMultiline.length, closeMultiline.length) !== closeMultiline) { textChanges.push({ newText: closeMultiline, span: { length: 0, start: positions[i] } }); } if (text.substr(positions[i], openMultiline.length) !== openMultiline) { textChanges.push({ newText: openMultiline, span: { length: 0, start: positions[i] } }); } } // Insert open comment if the last position is not a comment already. if (textChanges.length % 2 !== 0) { textChanges.push({ newText: closeMultiline, span: { length: 0, start: positions[positions.length - 1] } }); } } else { // If is not commenting then remove all comments found. for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) { var pos_2 = positions_1[_i]; var from = pos_2 - closeMultiline.length > 0 ? pos_2 - closeMultiline.length : 0; var offset = text.substr(from, closeMultiline.length) === closeMultiline ? closeMultiline.length : 0; textChanges.push({ newText: "", span: { length: openMultiline.length, start: pos_2 - offset } }); } } return textChanges; } function commentSelection(fileName, textRange) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var _a = getLinesForRange(sourceFile, textRange), firstLine = _a.firstLine, lastLine = _a.lastLine; // If there is a selection that is on the same line, add multiline. return firstLine === lastLine && textRange.pos !== textRange.end ? toggleMultilineComment(fileName, textRange, /*insertComment*/ true) : toggleLineComment(fileName, textRange, /*insertComment*/ true); } function uncommentSelection(fileName, textRange) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var textChanges = []; var pos = textRange.pos; var end = textRange.end; // If cursor is not a selection we need to increase the end position // to include the start of the comment. if (pos === end) { end += ts.isInsideJsxElement(sourceFile, pos) ? 2 : 1; } for (var i = pos; i <= end; i++) { var commentRange = ts.isInComment(sourceFile, i); if (commentRange) { switch (commentRange.kind) { case 2 /* SyntaxKind.SingleLineCommentTrivia */: textChanges.push.apply(textChanges, toggleLineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, /*insertComment*/ false)); break; case 3 /* SyntaxKind.MultiLineCommentTrivia */: textChanges.push.apply(textChanges, toggleMultilineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, /*insertComment*/ false)); } i = commentRange.end + 1; } } return textChanges; } function isUnclosedTag(_a) { var openingElement = _a.openingElement, closingElement = _a.closingElement, parent = _a.parent; return !ts.tagNamesAreEquivalent(openingElement.tagName, closingElement.tagName) || ts.isJsxElement(parent) && ts.tagNamesAreEquivalent(openingElement.tagName, parent.openingElement.tagName) && isUnclosedTag(parent); } function isUnclosedFragment(_a) { var closingFragment = _a.closingFragment, parent = _a.parent; return !!(closingFragment.flags & 131072 /* NodeFlags.ThisNodeHasError */) || (ts.isJsxFragment(parent) && isUnclosedFragment(parent)); } function getSpanOfEnclosingComment(fileName, position, onlyMultiLine) { var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); var range = ts.formatting.getRangeOfEnclosingComment(sourceFile, position); return range && (!onlyMultiLine || range.kind === 3 /* SyntaxKind.MultiLineCommentTrivia */) ? ts.createTextSpanFromRange(range) : undefined; } function getTodoComments(fileName, descriptors) { // Note: while getting todo comments seems like a syntactic operation, we actually // treat it as a semantic operation here. This is because we expect our host to call // this on every single file. If we treat this syntactically, then that will cause // us to populate and throw away the tree in our syntax tree cache for each file. By // treating this as a semantic operation, we can access any tree without throwing // anything away. synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); cancellationToken.throwIfCancellationRequested(); var fileContents = sourceFile.text; var result = []; // Exclude node_modules files as we don't want to show the todos of external libraries. if (descriptors.length > 0 && !isNodeModulesFile(sourceFile.fileName)) { var regExp = getTodoCommentsRegExp(); var matchArray = void 0; while (matchArray = regExp.exec(fileContents)) { cancellationToken.throwIfCancellationRequested(); // If we got a match, here is what the match array will look like. Say the source text is: // // " // hack 1" // // The result array with the regexp: will be: // // ["// hack 1", "// ", "hack 1", undefined, "hack"] // // Here are the relevant capture groups: // 0) The full match for the entire regexp. // 1) The preamble to the message portion. // 2) The message portion. // 3...N) The descriptor that was matched - by index. 'undefined' for each // descriptor that didn't match. an actual value if it did match. // // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. // "hack" in position 4 means HACK did match. var firstDescriptorCaptureIndex = 3; ts.Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); var preamble = matchArray[1]; var matchPosition = matchArray.index + preamble.length; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. if (!ts.isInComment(sourceFile, matchPosition)) { continue; } var descriptor = void 0; for (var i = 0; i < descriptors.length; i++) { if (matchArray[i + firstDescriptorCaptureIndex]) { descriptor = descriptors[i]; } } if (descriptor === undefined) return ts.Debug.fail(); // We don't want to match something like 'TODOBY', so we make sure a non // letter/digit follows the match. if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) { continue; } var message = matchArray[2]; result.push({ descriptor: descriptor, message: message, position: matchPosition }); } } return result; function escapeRegExp(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); } function getTodoCommentsRegExp() { // NOTE: `?:` means 'non-capture group'. It allows us to have groups without having to // filter them out later in the final result array. // TODO comments can appear in one of the following forms: // // 1) // TODO or /////////// TODO // // 2) /* TODO or /********** TODO // // 3) /* // * TODO // */ // // The following three regexps are used to match the start of the text up to the TODO // comment portion. var singleLineCommentStart = /(?:\/\/+\s*)/.source; var multiLineCommentStart = /(?:\/\*+\s*)/.source; var anyNumberOfSpacesAndAsterisksAtStartOfLine = /(?:^(?:\s|\*)*)/.source; // Match any of the above three TODO comment start regexps. // Note that the outermost group *is* a capture group. We want to capture the preamble // so that we can determine the starting position of the TODO comment match. var preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")"; // Takes the descriptors and forms a regexp that matches them as if they were literals. // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be: // // (?:(TODO\(jason\))|(HACK)) // // Note that the outermost group is *not* a capture group, but the innermost groups // *are* capture groups. By capturing the inner literals we can determine after // matching which descriptor we are dealing with. var literals = "(?:" + ts.map(descriptors, function (d) { return "(" + escapeRegExp(d.text) + ")"; }).join("|") + ")"; // After matching a descriptor literal, the following regexp matches the rest of the // text up to the end of the line (or */). var endOfLineOrEndOfComment = /(?:$|\*\/)/.source; var messageRemainder = /(?:.*?)/.source; // This is the portion of the match we'll return as part of the TODO comment result. We // match the literal portion up to the end of the line or end of comment. var messagePortion = "(" + literals + messageRemainder + ")"; var regExpString = preamble + messagePortion + endOfLineOrEndOfComment; // The final regexp will look like this: // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim // The flags of the regexp are important here. // 'g' is so that we are doing a global search and can find matches several times // in the input. // // 'i' is for case insensitivity (We do this to match C# TODO comment code). // // 'm' is so we can find matches in a multi-line input. return new RegExp(regExpString, "gim"); } function isLetterOrDigit(char) { return (char >= 97 /* CharacterCodes.a */ && char <= 122 /* CharacterCodes.z */) || (char >= 65 /* CharacterCodes.A */ && char <= 90 /* CharacterCodes.Z */) || (char >= 48 /* CharacterCodes._0 */ && char <= 57 /* CharacterCodes._9 */); } function isNodeModulesFile(path) { return ts.stringContains(path, "/node_modules/"); } } function getRenameInfo(fileName, position, options) { synchronizeHostData(); return ts.Rename.getRenameInfo(program, getValidSourceFile(fileName), position, options); } function getRefactorContext(file, positionOrRange, preferences, formatOptions, triggerReason, kind) { var _a = typeof positionOrRange === "number" ? [positionOrRange, undefined] : [positionOrRange.pos, positionOrRange.end], startPosition = _a[0], endPosition = _a[1]; return { file: file, startPosition: startPosition, endPosition: endPosition, program: getProgram(), host: host, formatContext: ts.formatting.getFormatContext(formatOptions, host), cancellationToken: cancellationToken, preferences: preferences, triggerReason: triggerReason, kind: kind }; } function getInlayHintsContext(file, span, preferences) { return { file: file, program: getProgram(), host: host, span: span, preferences: preferences, cancellationToken: cancellationToken, }; } function getSmartSelectionRange(fileName, position) { return ts.SmartSelectionRange.getSmartSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName)); } function getApplicableRefactors(fileName, positionOrRange, preferences, triggerReason, kind) { if (preferences === void 0) { preferences = ts.emptyOptions; } synchronizeHostData(); var file = getValidSourceFile(fileName); return ts.refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange, preferences, ts.emptyOptions, triggerReason, kind)); } function getEditsForRefactor(fileName, formatOptions, positionOrRange, refactorName, actionName, preferences) { if (preferences === void 0) { preferences = ts.emptyOptions; } synchronizeHostData(); var file = getValidSourceFile(fileName); return ts.refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, preferences, formatOptions), refactorName, actionName); } function toLineColumnOffset(fileName, position) { // Go to Definition supports returning a zero-length span at position 0 for // non-existent files. We need to special-case the conversion of position 0 // to avoid a crash trying to get the text for that file, since this function // otherwise assumes that 'fileName' is the name of a file that exists. if (position === 0) { return { line: 0, character: 0 }; } return sourceMapper.toLineColumnOffset(fileName, position); } function prepareCallHierarchy(fileName, position) { synchronizeHostData(); var declarations = ts.CallHierarchy.resolveCallHierarchyDeclaration(program, ts.getTouchingPropertyName(getValidSourceFile(fileName), position)); return declarations && ts.mapOneOrMany(declarations, function (declaration) { return ts.CallHierarchy.createCallHierarchyItem(program, declaration); }); } function provideCallHierarchyIncomingCalls(fileName, position) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var declaration = ts.firstOrOnly(ts.CallHierarchy.resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : ts.getTouchingPropertyName(sourceFile, position))); return declaration ? ts.CallHierarchy.getIncomingCalls(program, declaration, cancellationToken) : []; } function provideCallHierarchyOutgoingCalls(fileName, position) { synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); var declaration = ts.firstOrOnly(ts.CallHierarchy.resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : ts.getTouchingPropertyName(sourceFile, position))); return declaration ? ts.CallHierarchy.getOutgoingCalls(program, declaration) : []; } function provideInlayHints(fileName, span, preferences) { if (preferences === void 0) { preferences = ts.emptyOptions; } synchronizeHostData(); var sourceFile = getValidSourceFile(fileName); return ts.InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences)); } var ls = { dispose: dispose, cleanupSemanticCache: cleanupSemanticCache, getSyntacticDiagnostics: getSyntacticDiagnostics, getSemanticDiagnostics: getSemanticDiagnostics, getSuggestionDiagnostics: getSuggestionDiagnostics, getCompilerOptionsDiagnostics: getCompilerOptionsDiagnostics, getSyntacticClassifications: getSyntacticClassifications, getSemanticClassifications: getSemanticClassifications, getEncodedSyntacticClassifications: getEncodedSyntacticClassifications, getEncodedSemanticClassifications: getEncodedSemanticClassifications, getCompletionsAtPosition: getCompletionsAtPosition, getCompletionEntryDetails: getCompletionEntryDetails, getCompletionEntrySymbol: getCompletionEntrySymbol, getSignatureHelpItems: getSignatureHelpItems, getQuickInfoAtPosition: getQuickInfoAtPosition, getDefinitionAtPosition: getDefinitionAtPosition, getDefinitionAndBoundSpan: getDefinitionAndBoundSpan, getImplementationAtPosition: getImplementationAtPosition, getTypeDefinitionAtPosition: getTypeDefinitionAtPosition, getReferencesAtPosition: getReferencesAtPosition, findReferences: findReferences, getFileReferences: getFileReferences, getOccurrencesAtPosition: getOccurrencesAtPosition, getDocumentHighlights: getDocumentHighlights, getNameOrDottedNameSpan: getNameOrDottedNameSpan, getBreakpointStatementAtPosition: getBreakpointStatementAtPosition, getNavigateToItems: getNavigateToItems, getRenameInfo: getRenameInfo, getSmartSelectionRange: getSmartSelectionRange, findRenameLocations: findRenameLocations, getNavigationBarItems: getNavigationBarItems, getNavigationTree: getNavigationTree, getOutliningSpans: getOutliningSpans, getTodoComments: getTodoComments, getBraceMatchingAtPosition: getBraceMatchingAtPosition, getIndentationAtPosition: getIndentationAtPosition, getFormattingEditsForRange: getFormattingEditsForRange, getFormattingEditsForDocument: getFormattingEditsForDocument, getFormattingEditsAfterKeystroke: getFormattingEditsAfterKeystroke, getDocCommentTemplateAtPosition: getDocCommentTemplateAtPosition, isValidBraceCompletionAtPosition: isValidBraceCompletionAtPosition, getJsxClosingTagAtPosition: getJsxClosingTagAtPosition, getSpanOfEnclosingComment: getSpanOfEnclosingComment, getCodeFixesAtPosition: getCodeFixesAtPosition, getCombinedCodeFix: getCombinedCodeFix, applyCodeActionCommand: applyCodeActionCommand, organizeImports: organizeImports, getEditsForFileRename: getEditsForFileRename, getEmitOutput: getEmitOutput, getNonBoundSourceFile: getNonBoundSourceFile, getProgram: getProgram, getAutoImportProvider: getAutoImportProvider, getApplicableRefactors: getApplicableRefactors, getEditsForRefactor: getEditsForRefactor, toLineColumnOffset: toLineColumnOffset, getSourceMapper: function () { return sourceMapper; }, clearSourceMapperCache: function () { return sourceMapper.clearCache(); }, prepareCallHierarchy: prepareCallHierarchy, provideCallHierarchyIncomingCalls: provideCallHierarchyIncomingCalls, provideCallHierarchyOutgoingCalls: provideCallHierarchyOutgoingCalls, toggleLineComment: toggleLineComment, toggleMultilineComment: toggleMultilineComment, commentSelection: commentSelection, uncommentSelection: uncommentSelection, provideInlayHints: provideInlayHints, }; switch (languageServiceMode) { case ts.LanguageServiceMode.Semantic: break; case ts.LanguageServiceMode.PartialSemantic: invalidOperationsInPartialSemanticMode.forEach(function (key) { return ls[key] = function () { throw new Error("LanguageService Operation: ".concat(key, " not allowed in LanguageServiceMode.PartialSemantic")); }; }); break; case ts.LanguageServiceMode.Syntactic: invalidOperationsInSyntacticMode.forEach(function (key) { return ls[key] = function () { throw new Error("LanguageService Operation: ".concat(key, " not allowed in LanguageServiceMode.Syntactic")); }; }); break; default: ts.Debug.assertNever(languageServiceMode); } return ls; } ts.createLanguageService = createLanguageService; /* @internal */ /** Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`. */ function getNameTable(sourceFile) { if (!sourceFile.nameTable) { initializeNameTable(sourceFile); } return sourceFile.nameTable; // TODO: GH#18217 } ts.getNameTable = getNameTable; function initializeNameTable(sourceFile) { var nameTable = sourceFile.nameTable = new ts.Map(); sourceFile.forEachChild(function walk(node) { if (ts.isIdentifier(node) && !ts.isTagName(node) && node.escapedText || ts.isStringOrNumericLiteralLike(node) && literalIsName(node)) { var text = ts.getEscapedTextOfIdentifierOrLiteral(node); nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } else if (ts.isPrivateIdentifier(node)) { var text = node.escapedText; nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } ts.forEachChild(node, walk); if (ts.hasJSDocNodes(node)) { for (var _i = 0, _a = node.jsDoc; _i < _a.length; _i++) { var jsDoc = _a[_i]; ts.forEachChild(jsDoc, walk); } } }); } /** * We want to store any numbers/strings if they were a name that could be * related to a declaration. So, if we have 'import x = require("something")' * then we want 'something' to be in the name table. Similarly, if we have * "a['propname']" then we want to store "propname" in the name table. */ function literalIsName(node) { return ts.isDeclarationName(node) || node.parent.kind === 277 /* SyntaxKind.ExternalModuleReference */ || isArgumentOfElementAccessExpression(node) || ts.isLiteralComputedPropertyDeclarationName(node); } /** * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } */ /* @internal */ function getContainingObjectLiteralElement(node) { var element = getContainingObjectLiteralElementWorker(node); return element && (ts.isObjectLiteralExpression(element.parent) || ts.isJsxAttributes(element.parent)) ? element : undefined; } ts.getContainingObjectLiteralElement = getContainingObjectLiteralElement; function getContainingObjectLiteralElementWorker(node) { switch (node.kind) { case 10 /* SyntaxKind.StringLiteral */: case 14 /* SyntaxKind.NoSubstitutionTemplateLiteral */: case 8 /* SyntaxKind.NumericLiteral */: if (node.parent.kind === 162 /* SyntaxKind.ComputedPropertyName */) { return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined; } // falls through case 79 /* SyntaxKind.Identifier */: return ts.isObjectLiteralElement(node.parent) && (node.parent.parent.kind === 205 /* SyntaxKind.ObjectLiteralExpression */ || node.parent.parent.kind === 286 /* SyntaxKind.JsxAttributes */) && node.parent.name === node ? node.parent : undefined; } return undefined; } function getSymbolAtLocationForQuickInfo(node, checker) { var object = getContainingObjectLiteralElement(node); if (object) { var contextualType = checker.getContextualType(object.parent); var properties = contextualType && getPropertySymbolsFromContextualType(object, checker, contextualType, /*unionSymbolOk*/ false); if (properties && properties.length === 1) { return ts.first(properties); } } return checker.getSymbolAtLocation(node); } /** Gets all symbols for one property. Does not get symbols for every property. */ /* @internal */ function getPropertySymbolsFromContextualType(node, checker, contextualType, unionSymbolOk) { var name = ts.getNameFromPropertyName(node.name); if (!name) return ts.emptyArray; if (!contextualType.isUnion()) { var symbol = contextualType.getProperty(name); return symbol ? [symbol] : ts.emptyArray; } var discriminatedPropertySymbols = ts.mapDefined(contextualType.types, function (t) { return (ts.isObjectLiteralExpression(node.parent) || ts.isJsxAttributes(node.parent)) && checker.isTypeInvalidDueToUnionDiscriminant(t, node.parent) ? undefined : t.getProperty(name); }); if (unionSymbolOk && (discriminatedPropertySymbols.length === 0 || discriminatedPropertySymbols.length === contextualType.types.length)) { var symbol = contextualType.getProperty(name); if (symbol) return [symbol]; } if (discriminatedPropertySymbols.length === 0) { // Bad discriminant -- do again without discriminating return ts.mapDefined(contextualType.types, function (t) { return t.getProperty(name); }); } return discriminatedPropertySymbols; } ts.getPropertySymbolsFromContextualType = getPropertySymbolsFromContextualType; function isArgumentOfElementAccessExpression(node) { return node && node.parent && node.parent.kind === 207 /* SyntaxKind.ElementAccessExpression */ && node.parent.argumentExpression === node; } /** * Get the path of the default library files (lib.d.ts) as distributed with the typescript * node package. * The functionality is not supported if the ts module is consumed outside of a node module. */ function getDefaultLibFilePath(options) { // Check __dirname is defined and that we are on a node.js system. if (typeof __dirname !== "undefined") { return __dirname + ts.directorySeparator + ts.getDefaultLibFileName(options); } throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. "); } ts.getDefaultLibFilePath = getDefaultLibFilePath; ts.setObjectAllocator(getServicesObjectAllocator()); })(ts || (ts = {})); /* @internal */ var ts; (function (ts) { var BreakpointResolver; (function (BreakpointResolver) { /** * Get the breakpoint span in given sourceFile */ function spanInSourceFileAtLocation(sourceFile, position) { // Cannot set breakpoint in dts file if (sourceFile.isDeclarationFile) { return undefined; } var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position); var lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line; if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) { // Get previous token if the token is returned starts on new line // eg: let x =10; |--- cursor is here // let y = 10; // token at position will return let keyword on second line as the token but we would like to use // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line var preceding = ts.findPrecedingToken(tokenAtLocation.pos, sourceFile); // It's a blank line if (!preceding || sourceFile.getLineAndCharacterOfPosition(preceding.getEnd()).line !== lineOfPosition) { return undefined; } tokenAtLocation = preceding; } // Cannot set breakpoint in ambient declarations if (tokenAtLocation.flags & 16777216 /* NodeFlags.Ambient */) { return undefined; } // Get the span in the node based on its syntax return spanInNode(tokenAtLocation); function textSpan(startNode, endNode) { var start = startNode.decorators ? ts.skipTrivia(sourceFile.text, startNode.decorators.end) : startNode.getStart(sourceFile); return ts.createTextSpanFromBounds(start, (endNode || startNode).getEnd()); } function textSpanEndingAtNextToken(startNode, previousTokenToFindNextEndToken) { return textSpan(startNode, ts.findNextToken(previousTokenToFindNextEndToken, previousTokenToFindNextEndToken.parent, sourceFile)); } function spanInNodeIfStartsOnSameLine(node, otherwiseOnNode) { if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) { return spanInNode(node); } return spanInNode(otherwiseOnNode); } function spanInNodeArray(nodeArray) { return ts.createTextSpanFromBounds(ts.skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end); } function spanInPreviousNode(node) { return spanInNode(ts.findPrecedingToken(node.pos, sourceFile)); } function spanInNextNode(node) { return spanInNode(ts.findNextToken(node, node.parent, sourceFile)); } function spanInNode(node) { if (node) { var parent = node.parent; switch (node.kind) { case 237 /* SyntaxKind.VariableStatement */: // Span on first variable declaration return spanInVariableDeclaration(node.declarationList.declarations[0]); case 254 /* SyntaxKind.VariableDeclaration */: case 167 /* SyntaxKind.PropertyDeclaration */: case 166 /* SyntaxKind.PropertySignature */: return spanInVariableDeclaration(node); case 164 /* SyntaxKind.Parameter */: return spanInParameterDeclaration(node); case 256 /* SyntaxKind.FunctionDeclaration */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: case 171 /* SyntaxKind.Constructor */: case 213 /* SyntaxKind.FunctionExpression */: case 214 /* SyntaxKind.ArrowFunction */: return spanInFunctionDeclaration(node); case 235 /* SyntaxKind.Block */: if (ts.isFunctionBlock(node)) { return spanInFunctionBlock(node); } // falls through case 262 /* SyntaxKind.ModuleBlock */: return spanInBlock(node); case 292 /* SyntaxKind.CatchClause */: return spanInBlock(node.block); case 238 /* SyntaxKind.ExpressionStatement */: // span on the expression return textSpan(node.expression); case 247 /* SyntaxKind.ReturnStatement */: // span on return keyword and expression if present return textSpan(node.getChildAt(0), node.expression); case 241 /* SyntaxKind.WhileStatement */: // Span on while(...) return textSpanEndingAtNextToken(node, node.expression); case 240 /* SyntaxKind.DoStatement */: // span in statement of the do statement return spanInNode(node.statement); case 253 /* SyntaxKind.DebuggerStatement */: // span on debugger keyword return textSpan(node.getChildAt(0)); case 239 /* SyntaxKind.IfStatement */: // set on if(..) span return textSpanEndingAtNextToken(node, node.expression); case 250 /* SyntaxKind.LabeledStatement */: // span in statement return spanInNode(node.statement); case 246 /* SyntaxKind.BreakStatement */: case 245 /* SyntaxKind.ContinueStatement */: // On break or continue keyword and label if present return textSpan(node.getChildAt(0), node.label); case 242 /* SyntaxKind.ForStatement */: return spanInForStatement(node); case 243 /* SyntaxKind.ForInStatement */: // span of for (a in ...) return textSpanEndingAtNextToken(node, node.expression); case 244 /* SyntaxKind.ForOfStatement */: // span in initializer return spanInInitializerOfForLike(node); case 249 /* SyntaxKind.SwitchStatement */: // span on switch(...) return textSpanEndingAtNextToken(node, node.expression); case 289 /* SyntaxKind.CaseClause */: case 290 /* SyntaxKind.DefaultClause */: // span in first statement of the clause return spanInNode(node.statements[0]); case 252 /* SyntaxKind.TryStatement */: // span in try block return spanInBlock(node.tryBlock); case 251 /* SyntaxKind.ThrowStatement */: // span in throw ... return textSpan(node, node.expression); case 271 /* SyntaxKind.ExportAssignment */: // span on export = id return textSpan(node, node.expression); case 265 /* SyntaxKind.ImportEqualsDeclaration */: // import statement without including semicolon return textSpan(node, node.moduleReference); case 266 /* SyntaxKind.ImportDeclaration */: // import statement without including semicolon return textSpan(node, node.moduleSpecifier); case 272 /* SyntaxKind.ExportDeclaration */: // import statement without including semicolon return textSpan(node, node.moduleSpecifier); case 261 /* SyntaxKind.ModuleDeclaration */: // span on complete module if it is instantiated if (ts.getModuleInstanceState(node) !== 1 /* ModuleInstanceState.Instantiated */) { return undefined; } // falls through case 257 /* SyntaxKind.ClassDeclaration */: case 260 /* SyntaxKind.EnumDeclaration */: case 299 /* SyntaxKind.EnumMember */: case 203 /* SyntaxKind.BindingElement */: // span on complete node return textSpan(node); case 248 /* SyntaxKind.WithStatement */: // span in statement return spanInNode(node.statement); case 165 /* SyntaxKind.Decorator */: return spanInNodeArray(parent.decorators); case 201 /* SyntaxKind.ObjectBindingPattern */: case 202 /* SyntaxKind.ArrayBindingPattern */: return spanInBindingPattern(node); // No breakpoint in interface, type alias case 258 /* SyntaxKind.InterfaceDeclaration */: case 259 /* SyntaxKind.TypeAliasDeclaration */: return undefined; // Tokens: case 26 /* SyntaxKind.SemicolonToken */: case 1 /* SyntaxKind.EndOfFileToken */: return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile)); case 27 /* SyntaxKind.CommaToken */: return spanInPreviousNode(node); case 18 /* SyntaxKind.OpenBraceToken */: return spanInOpenBraceToken(node); case 19 /* SyntaxKind.CloseBraceToken */: return spanInCloseBraceToken(node); case 23 /* SyntaxKind.CloseBracketToken */: return spanInCloseBracketToken(node); case 20 /* SyntaxKind.OpenParenToken */: return spanInOpenParenToken(node); case 21 /* SyntaxKind.CloseParenToken */: return spanInCloseParenToken(node); case 58 /* SyntaxKind.ColonToken */: return spanInColonToken(node); case 31 /* SyntaxKind.GreaterThanToken */: case 29 /* SyntaxKind.LessThanToken */: return spanInGreaterThanOrLessThanToken(node); // Keywords: case 115 /* SyntaxKind.WhileKeyword */: return spanInWhileKeyword(node); case 91 /* SyntaxKind.ElseKeyword */: case 83 /* SyntaxKind.CatchKeyword */: case 96 /* SyntaxKind.FinallyKeyword */: return spanInNextNode(node); case 160 /* SyntaxKind.OfKeyword */: return spanInOfKeyword(node); default: // Destructuring pattern in destructuring assignment // [a, b, c] of // [a, b, c] = expression if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node)) { return spanInArrayLiteralOrObjectLiteralDestructuringPattern(node); } // Set breakpoint on identifier element of destructuring pattern // `a` or `...c` or `d: x` from // `[a, b, ...c]` or `{ a, b }` or `{ d: x }` from destructuring pattern if ((node.kind === 79 /* SyntaxKind.Identifier */ || node.kind === 225 /* SyntaxKind.SpreadElement */ || node.kind === 296 /* SyntaxKind.PropertyAssignment */ || node.kind === 297 /* SyntaxKind.ShorthandPropertyAssignment */) && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(parent)) { return textSpan(node); } if (node.kind === 221 /* SyntaxKind.BinaryExpression */) { var _a = node, left = _a.left, operatorToken = _a.operatorToken; // Set breakpoint in destructuring pattern if its destructuring assignment // [a, b, c] or {a, b, c} of // [a, b, c] = expression or // {a, b, c} = expression if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(left)) { return spanInArrayLiteralOrObjectLiteralDestructuringPattern(left); } if (operatorToken.kind === 63 /* SyntaxKind.EqualsToken */ && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { // Set breakpoint on assignment expression element of destructuring pattern // a = expression of // [a = expression, b, c] = someExpression or // { a = expression, b, c } = someExpression return textSpan(node); } if (operatorToken.kind === 27 /* SyntaxKind.CommaToken */) { return spanInNode(left); } } if (ts.isExpressionNode(node)) { switch (parent.kind) { case 240 /* SyntaxKind.DoStatement */: // Set span as if on while keyword return spanInPreviousNode(node); case 165 /* SyntaxKind.Decorator */: // Set breakpoint on the decorator emit return spanInNode(node.parent); case 242 /* SyntaxKind.ForStatement */: case 244 /* SyntaxKind.ForOfStatement */: return textSpan(node); case 221 /* SyntaxKind.BinaryExpression */: if (node.parent.operatorToken.kind === 27 /* SyntaxKind.CommaToken */) { // If this is a comma expression, the breakpoint is possible in this expression return textSpan(node); } break; case 214 /* SyntaxKind.ArrowFunction */: if (node.parent.body === node) { // If this is body of arrow function, it is allowed to have the breakpoint return textSpan(node); } break; } } switch (node.parent.kind) { case 296 /* SyntaxKind.PropertyAssignment */: // If this is name of property assignment, set breakpoint in the initializer if (node.parent.name === node && !ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent)) { return spanInNode(node.parent.initializer); } break; case 211 /* SyntaxKind.TypeAssertionExpression */: // Breakpoint in type assertion goes to its operand if (node.parent.type === node) { return spanInNextNode(node.parent.type); } break; case 254 /* SyntaxKind.VariableDeclaration */: case 164 /* SyntaxKind.Parameter */: { // initializer of variable/parameter declaration go to previous node var _b = node.parent, initializer = _b.initializer, type = _b.type; if (initializer === node || type === node || ts.isAssignmentOperator(node.kind)) { return spanInPreviousNode(node); } break; } case 221 /* SyntaxKind.BinaryExpression */: { var left = node.parent.left; if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(left) && node !== left) { // If initializer of destructuring assignment move to previous token return spanInPreviousNode(node); } break; } default: // return type of function go to previous token if (ts.isFunctionLike(node.parent) && node.parent.type === node) { return spanInPreviousNode(node); } } // Default go to parent to set the breakpoint return spanInNode(node.parent); } } function textSpanFromVariableDeclaration(variableDeclaration) { if (ts.isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) { // First declaration - include let keyword return textSpan(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration); } else { // Span only on this declaration return textSpan(variableDeclaration); } } function spanInVariableDeclaration(variableDeclaration) { // If declaration of for in statement, just set the span in parent if (variableDeclaration.parent.parent.kind === 243 /* SyntaxKind.ForInStatement */) { return spanInNode(variableDeclaration.parent.parent); } var parent = variableDeclaration.parent; // If this is a destructuring pattern, set breakpoint in binding pattern if (ts.isBindingPattern(variableDeclaration.name)) { return spanInBindingPattern(variableDeclaration.name); } // Breakpoint is possible in variableDeclaration only if there is initialization // or its declaration from 'for of' if (variableDeclaration.initializer || ts.hasSyntacticModifier(variableDeclaration, 1 /* ModifierFlags.Export */) || parent.parent.kind === 244 /* SyntaxKind.ForOfStatement */) { return textSpanFromVariableDeclaration(variableDeclaration); } if (ts.isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] !== variableDeclaration) { // If we cannot set breakpoint on this declaration, set it on previous one // Because the variable declaration may be binding pattern and // we would like to set breakpoint in last binding element if that's the case, // use preceding token instead return spanInNode(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent)); } } function canHaveSpanInParameterDeclaration(parameter) { // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier return !!parameter.initializer || parameter.dotDotDotToken !== undefined || ts.hasSyntacticModifier(parameter, 4 /* ModifierFlags.Public */ | 8 /* ModifierFlags.Private */); } function spanInParameterDeclaration(parameter) { if (ts.isBindingPattern(parameter.name)) { // Set breakpoint in binding pattern return spanInBindingPattern(parameter.name); } else if (canHaveSpanInParameterDeclaration(parameter)) { return textSpan(parameter); } else { var functionDeclaration = parameter.parent; var indexOfParameter = functionDeclaration.parameters.indexOf(parameter); ts.Debug.assert(indexOfParameter !== -1); if (indexOfParameter !== 0) { // Not a first parameter, go to previous parameter return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]); } else { // Set breakpoint in the function declaration body return spanInNode(functionDeclaration.body); } } } function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) { return ts.hasSyntacticModifier(functionDeclaration, 1 /* ModifierFlags.Export */) || (functionDeclaration.parent.kind === 257 /* SyntaxKind.ClassDeclaration */ && functionDeclaration.kind !== 171 /* SyntaxKind.Constructor */); } function spanInFunctionDeclaration(functionDeclaration) { // No breakpoints in the function signature if (!functionDeclaration.body) { return undefined; } if (canFunctionHaveSpanInWholeDeclaration(functionDeclaration)) { // Set the span on whole function declaration return textSpan(functionDeclaration); } // Set span in function body return spanInNode(functionDeclaration.body); } function spanInFunctionBlock(block) { var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken(); if (canFunctionHaveSpanInWholeDeclaration(block.parent)) { return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock); } return spanInNode(nodeForSpanInBlock); } function spanInBlock(block) { switch (block.parent.kind) { case 261 /* SyntaxKind.ModuleDeclaration */: if (ts.getModuleInstanceState(block.parent) !== 1 /* ModuleInstanceState.Instantiated */) { return undefined; } // Set on parent if on same line otherwise on first statement // falls through case 241 /* SyntaxKind.WhileStatement */: case 239 /* SyntaxKind.IfStatement */: case 243 /* SyntaxKind.ForInStatement */: return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]); // Set span on previous token if it starts on same line otherwise on the first statement of the block case 242 /* SyntaxKind.ForStatement */: case 244 /* SyntaxKind.ForOfStatement */: return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]); } // Default action is to set on first statement return spanInNode(block.statements[0]); } function spanInInitializerOfForLike(forLikeStatement) { if (forLikeStatement.initializer.kind === 255 /* SyntaxKind.VariableDeclarationList */) { // Declaration list - set breakpoint in first declaration var variableDeclarationList = forLikeStatement.initializer; if (variableDeclarationList.declarations.length > 0) { return spanInNode(variableDeclarationList.declarations[0]); } } else { // Expression - set breakpoint in it return spanInNode(forLikeStatement.initializer); } } function spanInForStatement(forStatement) { if (forStatement.initializer) { return spanInInitializerOfForLike(forStatement); } if (forStatement.condition) { return textSpan(forStatement.condition); } if (forStatement.incrementor) { return textSpan(forStatement.incrementor); } } function spanInBindingPattern(bindingPattern) { // Set breakpoint in first binding element var firstBindingElement = ts.forEach(bindingPattern.elements, function (element) { return element.kind !== 227 /* SyntaxKind.OmittedExpression */ ? element : undefined; }); if (firstBindingElement) { return spanInNode(firstBindingElement); } // Empty binding pattern of binding element, set breakpoint on binding element if (bindingPattern.parent.kind === 203 /* SyntaxKind.BindingElement */) { return textSpan(bindingPattern.parent); } // Variable declaration is used as the span return textSpanFromVariableDeclaration(bindingPattern.parent); } function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node) { ts.Debug.assert(node.kind !== 202 /* SyntaxKind.ArrayBindingPattern */ && node.kind !== 201 /* SyntaxKind.ObjectBindingPattern */); var elements = node.kind === 204 /* SyntaxKind.ArrayLiteralExpression */ ? node.elements : node.properties; var firstBindingElement = ts.forEach(elements, function (element) { return element.kind !== 227 /* SyntaxKind.OmittedExpression */ ? element : undefined; }); if (firstBindingElement) { return spanInNode(firstBindingElement); } // Could be ArrayLiteral from destructuring assignment or // just nested element in another destructuring assignment // set breakpoint on assignment when parent is destructuring assignment // Otherwise set breakpoint for this element return textSpan(node.parent.kind === 221 /* SyntaxKind.BinaryExpression */ ? node.parent : node); } // Tokens: function spanInOpenBraceToken(node) { switch (node.parent.kind) { case 260 /* SyntaxKind.EnumDeclaration */: var enumDeclaration = node.parent; return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile)); case 257 /* SyntaxKind.ClassDeclaration */: var classDeclaration = node.parent; return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile)); case 263 /* SyntaxKind.CaseBlock */: return spanInNodeIfStartsOnSameLine(node.parent.parent, node.parent.clauses[0]); } // Default to parent node return spanInNode(node.parent); } function spanInCloseBraceToken(node) { switch (node.parent.kind) { case 262 /* SyntaxKind.ModuleBlock */: // If this is not an instantiated module block, no bp span if (ts.getModuleInstanceState(node.parent.parent) !== 1 /* ModuleInstanceState.Instantiated */) { return undefined; } // falls through case 260 /* SyntaxKind.EnumDeclaration */: case 257 /* SyntaxKind.ClassDeclaration */: // Span on close brace token return textSpan(node); case 235 /* SyntaxKind.Block */: if (ts.isFunctionBlock(node.parent)) { // Span on close brace token return textSpan(node); } // falls through case 292 /* SyntaxKind.CatchClause */: return spanInNode(ts.lastOrUndefined(node.parent.statements)); case 263 /* SyntaxKind.CaseBlock */: // breakpoint in last statement of the last clause var caseBlock = node.parent; var lastClause = ts.lastOrUndefined(caseBlock.clauses); if (lastClause) { return spanInNode(ts.lastOrUndefined(lastClause.statements)); } return undefined; case 201 /* SyntaxKind.ObjectBindingPattern */: // Breakpoint in last binding element or binding pattern if it contains no elements var bindingPattern = node.parent; return spanInNode(ts.lastOrUndefined(bindingPattern.elements) || bindingPattern); // Default to parent node default: if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { // Breakpoint in last binding element or binding pattern if it contains no elements var objectLiteral = node.parent; return textSpan(ts.lastOrUndefined(objectLiteral.properties) || objectLiteral); } return spanInNode(node.parent); } } function spanInCloseBracketToken(node) { switch (node.parent.kind) { case 202 /* SyntaxKind.ArrayBindingPattern */: // Breakpoint in last binding element or binding pattern if it contains no elements var bindingPattern = node.parent; return textSpan(ts.lastOrUndefined(bindingPattern.elements) || bindingPattern); default: if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) { // Breakpoint in last binding element or binding pattern if it contains no elements var arrayLiteral = node.parent; return textSpan(ts.lastOrUndefined(arrayLiteral.elements) || arrayLiteral); } // Default to parent node return spanInNode(node.parent); } } function spanInOpenParenToken(node) { if (node.parent.kind === 240 /* SyntaxKind.DoStatement */ || // Go to while keyword and do action instead node.parent.kind === 208 /* SyntaxKind.CallExpression */ || node.parent.kind === 209 /* SyntaxKind.NewExpression */) { return spanInPreviousNode(node); } if (node.parent.kind === 212 /* SyntaxKind.ParenthesizedExpression */) { return spanInNextNode(node); } // Default to parent node return spanInNode(node.parent); } function spanInCloseParenToken(node) { // Is this close paren token of parameter list, set span in previous token switch (node.parent.kind) { case 213 /* SyntaxKind.FunctionExpression */: case 256 /* SyntaxKind.FunctionDeclaration */: case 214 /* SyntaxKind.ArrowFunction */: case 169 /* SyntaxKind.MethodDeclaration */: case 168 /* SyntaxKind.MethodSignature */: case 172 /* SyntaxKind.GetAccessor */: case 173 /* SyntaxKind.SetAccessor */: case 171 /* SyntaxKind.Constructor */: case 241 /* SyntaxKind.WhileStatement */: case 240 /* SyntaxKind.DoStatement */: case 242 /* SyntaxKind.ForStatement */: case 244 /* SyntaxKind.ForOfStatement */: case 208 /* SyntaxKind.CallExpression */: case 209 /* SyntaxKind.NewExpression */: case 212 /* SyntaxKind.ParenthesizedExpression */: return spanInPreviousNode(node); // Default to parent node default: return spanInNode(node.parent); } } function spanInColonToken(node) { // Is this : specifying return annotation of the function declaration if (ts.isFunctionLike(node.parent) || node.parent.kind === 296 /* SyntaxKind.PropertyAssignment */ || node.parent.kind === 164 /* SyntaxKind.Parameter */) { return spanInPreviousNode(node); } return spanInNode(node.parent); } function spanInGreaterThanOrLessThanToken(node) { if (node.parent.kind === 211 /* SyntaxKind.TypeAssertionExpression */) { return spanInNextNode(node); } return spanInNode(node.parent); } function spanInWhileKeyword(node) { if (node.parent.kind === 240 /* SyntaxKind.DoStatement */) { // Set span on while expression return textSpanEndingAtNextToken(node, node.parent.expression); } // Default to parent node return spanInNode(node.parent); } function spanInOfKeyword(node) { if (node.parent.kind === 244 /* SyntaxKind.ForOfStatement */) { // Set using next token return spanInNextNode(node); } // Default to parent node return spanInNode(node.parent); } } } BreakpointResolver.spanInSourceFileAtLocation = spanInSourceFileAtLocation; })(BreakpointResolver = ts.BreakpointResolver || (ts.BreakpointResolver = {})); })(ts || (ts = {})); var ts; (function (ts) { /** * Transform one or more nodes using the supplied transformers. * @param source A single `Node` or an array of `Node` objects. * @param transformers An array of `TransformerFactory` callbacks used to process the transformation. * @param compilerOptions Optional compiler options. */ function transform(source, transformers, compilerOptions) { var diagnostics = []; compilerOptions = ts.fixupCompilerOptions(compilerOptions, diagnostics); // TODO: GH#18217 var nodes = ts.isArray(source) ? source : [source]; var result = ts.transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, ts.factory, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); result.diagnostics = ts.concatenate(result.diagnostics, diagnostics); return result; } ts.transform = transform; })(ts || (ts = {})); // // Copyright (c) Microsoft Corporation. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* @internal */ var debugObjectHost = (function () { return this; })(); // We need to use 'null' to interface with the managed side. /* eslint-disable no-in-operator */ /* @internal */ var ts; (function (ts) { function logInternalError(logger, err) { if (logger) { logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message); } } var ScriptSnapshotShimAdapter = /** @class */ (function () { function ScriptSnapshotShimAdapter(scriptSnapshotShim) { this.scriptSnapshotShim = scriptSnapshotShim; } ScriptSnapshotShimAdapter.prototype.getText = function (start, end) { return this.scriptSnapshotShim.getText(start, end); }; ScriptSnapshotShimAdapter.prototype.getLength = function () { return this.scriptSnapshotShim.getLength(); }; ScriptSnapshotShimAdapter.prototype.getChangeRange = function (oldSnapshot) { var oldSnapshotShim = oldSnapshot; var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim); /* eslint-disable no-null/no-null */ if (encoded === null) { return null; // TODO: GH#18217 } /* eslint-enable no-null/no-null */ var decoded = JSON.parse(encoded); // TODO: GH#18217 return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); }; ScriptSnapshotShimAdapter.prototype.dispose = function () { // if scriptSnapshotShim is a COM object then property check becomes method call with no arguments // 'in' does not have this effect if ("dispose" in this.scriptSnapshotShim) { this.scriptSnapshotShim.dispose(); // TODO: GH#18217 Can we just use `if (this.scriptSnapshotShim.dispose)`? } }; return ScriptSnapshotShimAdapter; }()); var LanguageServiceShimHostAdapter = /** @class */ (function () { function LanguageServiceShimHostAdapter(shimHost) { var _this = this; this.shimHost = shimHost; this.loggingEnabled = false; this.tracingEnabled = false; // if shimHost is a COM object then property check will become method call with no arguments. // 'in' does not have this effect. if ("getModuleResolutionsForFile" in this.shimHost) { this.resolveModuleNames = function (moduleNames, containingFile) { var resolutionsInFile = JSON.parse(_this.shimHost.getModuleResolutionsForFile(containingFile)); // TODO: GH#18217 return ts.map(moduleNames, function (name) { var result = ts.getProperty(resolutionsInFile, name); return result ? { resolvedFileName: result, extension: ts.extensionFromPath(result), isExternalLibraryImport: false } : undefined; }); }; } if ("directoryExists" in this.shimHost) { this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); }; } if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) { this.resolveTypeReferenceDirectives = function (typeDirectiveNames, containingFile) { var typeDirectivesForFile = JSON.parse(_this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile)); // TODO: GH#18217 return ts.map(typeDirectiveNames, function (name) { return ts.getProperty(typeDirectivesForFile, ts.isString(name) ? name : name.fileName.toLowerCase()); }); }; } } LanguageServiceShimHostAdapter.prototype.log = function (s) { if (this.loggingEnabled) { this.shimHost.log(s); } }; LanguageServiceShimHostAdapter.prototype.trace = function (s) { if (this.tracingEnabled) { this.shimHost.trace(s); } }; LanguageServiceShimHostAdapter.prototype.error = function (s) { this.shimHost.error(s); }; LanguageServiceShimHostAdapter.prototype.getProjectVersion = function () { if (!this.shimHost.getProjectVersion) { // shimmed host does not support getProjectVersion return undefined; // TODO: GH#18217 } return this.shimHost.getProjectVersion(); }; LanguageServiceShimHostAdapter.prototype.getTypeRootsVersion = function () { if (!this.shimHost.getTypeRootsVersion) { return 0; } return this.shimHost.getTypeRootsVersion(); }; LanguageServiceShimHostAdapter.prototype.useCaseSensitiveFileNames = function () { return this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false; }; LanguageServiceShimHostAdapter.prototype.getCompilationSettings = function () { var settingsJson = this.shimHost.getCompilationSettings(); // eslint-disable-next-line no-null/no-null if (settingsJson === null || settingsJson === "") { throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings"); } var compilerOptions = JSON.parse(settingsJson); // permit language service to handle all files (filtering should be performed on the host side) compilerOptions.allowNonTsExtensions = true; return compilerOptions; }; LanguageServiceShimHostAdapter.prototype.getScriptFileNames = function () { var encoded = this.shimHost.getScriptFileNames(); return JSON.parse(encoded); }; LanguageServiceShimHostAdapter.prototype.getScriptSnapshot = function (fileName) { var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName); return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot); }; LanguageServiceShimHostAdapter.prototype.getScriptKind = function (fileName) { if ("getScriptKind" in this.shimHost) { return this.shimHost.getScriptKind(fileName); // TODO: GH#18217 } else { return 0 /* ScriptKind.Unknown */; } }; LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) { return this.shimHost.getScriptVersion(fileName); }; LanguageServiceShimHostAdapter.prototype.getLocalizedDiagnosticMessages = function () { /* eslint-disable no-null/no-null */ var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages(); if (diagnosticMessagesJson === null || diagnosticMessagesJson === "") { return null; } try { return JSON.parse(diagnosticMessagesJson); } catch (e) { this.log(e.description || "diagnosticMessages.generated.json has invalid JSON format"); return null; } /* eslint-enable no-null/no-null */ }; LanguageServiceShimHostAdapter.prototype.getCancellationToken = function () { var hostCancellationToken = this.shimHost.getCancellationToken(); return new ts.ThrottledCancellationToken(hostCancellationToken); }; LanguageServiceShimHostAdapter.prototype.getCurrentDirectory = function () { return this.shimHost.getCurrentDirectory(); }; LanguageServiceShimHostAdapter.prototype.getDirectories = function (path) { return JSON.parse(this.shimHost.getDirectories(path)); }; LanguageServiceShimHostAdapter.prototype.getDefaultLibFileName = function (options) { return this.shimHost.getDefaultLibFileName(JSON.stringify(options)); }; LanguageServiceShimHostAdapter.prototype.readDirectory = function (path, extensions, exclude, include, depth) { var pattern = ts.getFileMatcherPatterns(path, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory(path, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth)); }; LanguageServiceShimHostAdapter.prototype.readFile = function (path, encoding) { return this.shimHost.readFile(path, encoding); }; LanguageServiceShimHostAdapter.prototype.fileExists = function (path) { return this.shimHost.fileExists(path); }; return LanguageServiceShimHostAdapter; }()); ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter; var CoreServicesShimHostAdapter = /** @class */ (function () { function CoreServicesShimHostAdapter(shimHost) { var _this = this; this.shimHost = shimHost; this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false; if ("directoryExists" in this.shimHost) { this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); }; } else { this.directoryExists = undefined; // TODO: GH#18217 } if ("realpath" in this.shimHost) { this.realpath = function (path) { return _this.shimHost.realpath(path); }; // TODO: GH#18217 } else { this.realpath = undefined; // TODO: GH#18217 } } CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extensions, exclude, include, depth) { var pattern = ts.getFileMatcherPatterns(rootDir, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory(rootDir, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth)); }; CoreServicesShimHostAdapter.prototype.fileExists = function (fileName) { return this.shimHost.fileExists(fileName); }; CoreServicesShimHostAdapter.prototype.readFile = function (fileName) { return this.shimHost.readFile(fileName); }; CoreServicesShimHostAdapter.prototype.getDirectories = function (path) { return JSON.parse(this.shimHost.getDirectories(path)); }; return CoreServicesShimHostAdapter; }()); ts.CoreServicesShimHostAdapter = CoreServicesShimHostAdapter; function simpleForwardCall(logger, actionDescription, action, logPerformance) { var start; if (logPerformance) { logger.log(actionDescription); start = ts.timestamp(); } var result = action(); if (logPerformance) { var end = ts.timestamp(); logger.log("".concat(actionDescription, " completed in ").concat(end - start, " msec")); if (ts.isString(result)) { var str = result; if (str.length > 128) { str = str.substring(0, 128) + "..."; } logger.log(" result.length=".concat(str.length, ", result='").concat(JSON.stringify(str), "'")); } } return result; } function forwardJSONCall(logger, actionDescription, action, logPerformance) { return forwardCall(logger, actionDescription, /*returnJson*/ true, action, logPerformance); } function forwardCall(logger, actionDescription, returnJson, action, logPerformance) { try { var result = simpleForwardCall(logger, actionDescription, action, logPerformance); return returnJson ? JSON.stringify({ result: result }) : result; } catch (err) { if (err instanceof ts.OperationCanceledException) { return JSON.stringify({ canceled: true }); } logInternalError(logger, err); err.description = actionDescription; return JSON.stringify({ error: err }); } } var ShimBase = /** @class */ (function () { function ShimBase(factory) { this.factory = factory; factory.registerShim(this); } ShimBase.prototype.dispose = function (_dummy) { this.factory.unregisterShim(this); }; return ShimBase; }()); function realizeDiagnostics(diagnostics, newLine) { return diagnostics.map(function (d) { return realizeDiagnostic(d, newLine); }); } ts.realizeDiagnostics = realizeDiagnostics; function realizeDiagnostic(diagnostic, newLine) { return { message: ts.flattenDiagnosticMessageText(diagnostic.messageText, newLine), start: diagnostic.start, length: diagnostic.length, category: ts.diagnosticCategoryName(diagnostic), code: diagnostic.code, reportsUnnecessary: diagnostic.reportsUnnecessary, reportsDeprecated: diagnostic.reportsDeprecated }; } var LanguageServiceShimObject = /** @class */ (function (_super) { __extends(LanguageServiceShimObject, _super); function LanguageServiceShimObject(factory, host, languageService) { var _this = _super.call(this, factory) || this; _this.host = host; _this.languageService = languageService; _this.logPerformance = false; _this.logger = _this.host; return _this; } LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) { return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance); }; /// DISPOSE /** * Ensure (almost) deterministic release of internal Javascript resources when * some external native objects holds onto us (e.g. Com/Interop). */ LanguageServiceShimObject.prototype.dispose = function (dummy) { this.logger.log("dispose()"); this.languageService.dispose(); this.languageService = null; // eslint-disable-line no-null/no-null // force a GC if (debugObjectHost && debugObjectHost.CollectGarbage) { debugObjectHost.CollectGarbage(); this.logger.log("CollectGarbage()"); } this.logger = null; // eslint-disable-line no-null/no-null _super.prototype.dispose.call(this, dummy); }; /// REFRESH /** * Update the list of scripts known to the compiler */ LanguageServiceShimObject.prototype.refresh = function (throwOnError) { this.forwardJSONCall("refresh(".concat(throwOnError, ")"), function () { return null; } // eslint-disable-line no-null/no-null ); }; LanguageServiceShimObject.prototype.cleanupSemanticCache = function () { var _this = this; this.forwardJSONCall("cleanupSemanticCache()", function () { _this.languageService.cleanupSemanticCache(); return null; // eslint-disable-line no-null/no-null }); }; LanguageServiceShimObject.prototype.realizeDiagnostics = function (diagnostics) { var newLine = ts.getNewLineOrDefaultFromHost(this.host); return realizeDiagnostics(diagnostics, newLine); }; LanguageServiceShimObject.prototype.getSyntacticClassifications = function (fileName, start, length) { var _this = this; return this.forwardJSONCall("getSyntacticClassifications('".concat(fileName, "', ").concat(start, ", ").concat(length, ")"), function () { return _this.languageService.getSyntacticClassifications(fileName, ts.createTextSpan(start, length)); }); }; LanguageServiceShimObject.prototype.getSemanticClassifications = function (fileName, start, length) { var _this = this; return this.forwardJSONCall("getSemanticClassifications('".concat(fileName, "', ").concat(start, ", ").concat(length, ")"), function () { return _this.languageService.getSemanticClassifications(fileName, ts.createTextSpan(start, length)); }); }; LanguageServiceShimObject.prototype.getEncodedSyntacticClassifications = function (fileName, start, length) { var _this = this; return this.forwardJSONCall("getEncodedSyntacticClassifications('".concat(fileName, "', ").concat(start, ", ").concat(length, ")"), // directly serialize the spans out to a string. This is much faster to decode // on the managed side versus a full JSON array. function () { return convertClassifications(_this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))); }); }; LanguageServiceShimObject.prototype.getEncodedSemanticClassifications = function (fileName, start, length) { var _this = this; return this.forwardJSONCall("getEncodedSemanticClassifications('".concat(fileName, "', ").concat(start, ", ").concat(length, ")"), // directly serialize the spans out to a string. This is much faster to decode // on the managed side versus a full JSON array. function () { return convertClassifications(_this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))); }); }; LanguageServiceShimObject.prototype.getSyntacticDiagnostics = function (fileName) { var _this = this; return this.forwardJSONCall("getSyntacticDiagnostics('".concat(fileName, "')"), function () { var diagnostics = _this.languageService.getSyntacticDiagnostics(fileName); return _this.realizeDiagnostics(diagnostics); }); }; LanguageServiceShimObject.prototype.getSemanticDiagnostics = function (fileName) { var _this = this; return this.forwardJSONCall("getSemanticDiagnostics('".concat(fileName, "')"), function () { var diagnostics = _this.languageService.getSemanticDiagnostics(fileName); return _this.realizeDiagnostics(diagnostics); }); }; LanguageServiceShimObject.prototype.getSuggestionDiagnostics = function (fileName) { var _this = this; return this.forwardJSONCall("getSuggestionDiagnostics('".concat(fileName, "')"), function () { return _this.realizeDiagnostics(_this.languageService.getSuggestionDiagnostics(fileName)); }); }; LanguageServiceShimObject.prototype.getCompilerOptionsDiagnostics = function () { var _this = this; return this.forwardJSONCall("getCompilerOptionsDiagnostics()", function () { var diagnostics = _this.languageService.getCompilerOptionsDiagnostics(); return _this.realizeDiagnostics(diagnostics); }); }; /// QUICKINFO /** * Computes a string representation of the type at the requested position * in the active file. */ LanguageServiceShimObject.prototype.getQuickInfoAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getQuickInfoAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getQuickInfoAtPosition(fileName, position); }); }; /// NAMEORDOTTEDNAMESPAN /** * Computes span information of the name or dotted name at the requested position * in the active file. */ LanguageServiceShimObject.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) { var _this = this; return this.forwardJSONCall("getNameOrDottedNameSpan('".concat(fileName, "', ").concat(startPos, ", ").concat(endPos, ")"), function () { return _this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos); }); }; /** * STATEMENTSPAN * Computes span information of statement at the requested position in the active file. */ LanguageServiceShimObject.prototype.getBreakpointStatementAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getBreakpointStatementAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getBreakpointStatementAtPosition(fileName, position); }); }; /// SIGNATUREHELP LanguageServiceShimObject.prototype.getSignatureHelpItems = function (fileName, position, options) { var _this = this; return this.forwardJSONCall("getSignatureHelpItems('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getSignatureHelpItems(fileName, position, options); }); }; /// GOTO DEFINITION /** * Computes the definition location and file for the symbol * at the requested position. */ LanguageServiceShimObject.prototype.getDefinitionAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getDefinitionAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getDefinitionAtPosition(fileName, position); }); }; /** * Computes the definition location and file for the symbol * at the requested position. */ LanguageServiceShimObject.prototype.getDefinitionAndBoundSpan = function (fileName, position) { var _this = this; return this.forwardJSONCall("getDefinitionAndBoundSpan('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getDefinitionAndBoundSpan(fileName, position); }); }; /// GOTO Type /** * Computes the definition location of the type of the symbol * at the requested position. */ LanguageServiceShimObject.prototype.getTypeDefinitionAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getTypeDefinitionAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getTypeDefinitionAtPosition(fileName, position); }); }; /// GOTO Implementation /** * Computes the implementation location of the symbol * at the requested position. */ LanguageServiceShimObject.prototype.getImplementationAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getImplementationAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getImplementationAtPosition(fileName, position); }); }; LanguageServiceShimObject.prototype.getRenameInfo = function (fileName, position, options) { var _this = this; return this.forwardJSONCall("getRenameInfo('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getRenameInfo(fileName, position, options); }); }; LanguageServiceShimObject.prototype.getSmartSelectionRange = function (fileName, position) { var _this = this; return this.forwardJSONCall("getSmartSelectionRange('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getSmartSelectionRange(fileName, position); }); }; LanguageServiceShimObject.prototype.findRenameLocations = function (fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename) { var _this = this; return this.forwardJSONCall("findRenameLocations('".concat(fileName, "', ").concat(position, ", ").concat(findInStrings, ", ").concat(findInComments, ", ").concat(providePrefixAndSuffixTextForRename, ")"), function () { return _this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename); }); }; /// GET BRACE MATCHING LanguageServiceShimObject.prototype.getBraceMatchingAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getBraceMatchingAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getBraceMatchingAtPosition(fileName, position); }); }; LanguageServiceShimObject.prototype.isValidBraceCompletionAtPosition = function (fileName, position, openingBrace) { var _this = this; return this.forwardJSONCall("isValidBraceCompletionAtPosition('".concat(fileName, "', ").concat(position, ", ").concat(openingBrace, ")"), function () { return _this.languageService.isValidBraceCompletionAtPosition(fileName, position, openingBrace); }); }; LanguageServiceShimObject.prototype.getSpanOfEnclosingComment = function (fileName, position, onlyMultiLine) { var _this = this; return this.forwardJSONCall("getSpanOfEnclosingComment('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getSpanOfEnclosingComment(fileName, position, onlyMultiLine); }); }; /// GET SMART INDENT LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options /*Services.EditorOptions*/) { var _this = this; return this.forwardJSONCall("getIndentationAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { var localOptions = JSON.parse(options); return _this.languageService.getIndentationAtPosition(fileName, position, localOptions); }); }; /// GET REFERENCES LanguageServiceShimObject.prototype.getReferencesAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getReferencesAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getReferencesAtPosition(fileName, position); }); }; LanguageServiceShimObject.prototype.findReferences = function (fileName, position) { var _this = this; return this.forwardJSONCall("findReferences('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.findReferences(fileName, position); }); }; LanguageServiceShimObject.prototype.getFileReferences = function (fileName) { var _this = this; return this.forwardJSONCall("getFileReferences('".concat(fileName, ")"), function () { return _this.languageService.getFileReferences(fileName); }); }; LanguageServiceShimObject.prototype.getOccurrencesAtPosition = function (fileName, position) { var _this = this; return this.forwardJSONCall("getOccurrencesAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getOccurrencesAtPosition(fileName, position); }); }; LanguageServiceShimObject.prototype.getDocumentHighlights = function (fileName, position, filesToSearch) { var _this = this; return this.forwardJSONCall("getDocumentHighlights('".concat(fileName, "', ").concat(position, ")"), function () { var results = _this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); // workaround for VS document highlighting issue - keep only items from the initial file var normalizedName = ts.toFileNameLowerCase(ts.normalizeSlashes(fileName)); return ts.filter(results, function (r) { return ts.toFileNameLowerCase(ts.normalizeSlashes(r.fileName)) === normalizedName; }); }); }; /// COMPLETION LISTS /** * Get a string based representation of the completions * to provide at the given source position and providing a member completion * list if requested. */ LanguageServiceShimObject.prototype.getCompletionsAtPosition = function (fileName, position, preferences, formattingSettings) { var _this = this; return this.forwardJSONCall("getCompletionsAtPosition('".concat(fileName, "', ").concat(position, ", ").concat(preferences, ", ").concat(formattingSettings, ")"), function () { return _this.languageService.getCompletionsAtPosition(fileName, position, preferences, formattingSettings); }); }; /** Get a string based representation of a completion list entry details */ LanguageServiceShimObject.prototype.getCompletionEntryDetails = function (fileName, position, entryName, formatOptions, source, preferences, data) { var _this = this; return this.forwardJSONCall("getCompletionEntryDetails('".concat(fileName, "', ").concat(position, ", '").concat(entryName, "')"), function () { var localOptions = formatOptions === undefined ? undefined : JSON.parse(formatOptions); return _this.languageService.getCompletionEntryDetails(fileName, position, entryName, localOptions, source, preferences, data); }); }; LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsForRange('".concat(fileName, "', ").concat(start, ", ").concat(end, ")"), function () { var localOptions = JSON.parse(options); return _this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions); }); }; LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsForDocument('".concat(fileName, "')"), function () { var localOptions = JSON.parse(options); return _this.languageService.getFormattingEditsForDocument(fileName, localOptions); }); }; LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options /*Services.FormatCodeOptions*/) { var _this = this; return this.forwardJSONCall("getFormattingEditsAfterKeystroke('".concat(fileName, "', ").concat(position, ", '").concat(key, "')"), function () { var localOptions = JSON.parse(options); return _this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions); }); }; LanguageServiceShimObject.prototype.getDocCommentTemplateAtPosition = function (fileName, position, options) { var _this = this; return this.forwardJSONCall("getDocCommentTemplateAtPosition('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.getDocCommentTemplateAtPosition(fileName, position, options); }); }; /// NAVIGATE TO /** Return a list of symbols that are interesting to navigate to */ LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount, fileName) { var _this = this; return this.forwardJSONCall("getNavigateToItems('".concat(searchValue, "', ").concat(maxResultCount, ", ").concat(fileName, ")"), function () { return _this.languageService.getNavigateToItems(searchValue, maxResultCount, fileName); }); }; LanguageServiceShimObject.prototype.getNavigationBarItems = function (fileName) { var _this = this; return this.forwardJSONCall("getNavigationBarItems('".concat(fileName, "')"), function () { return _this.languageService.getNavigationBarItems(fileName); }); }; LanguageServiceShimObject.prototype.getNavigationTree = function (fileName) { var _this = this; return this.forwardJSONCall("getNavigationTree('".concat(fileName, "')"), function () { return _this.languageService.getNavigationTree(fileName); }); }; LanguageServiceShimObject.prototype.getOutliningSpans = function (fileName) { var _this = this; return this.forwardJSONCall("getOutliningSpans('".concat(fileName, "')"), function () { return _this.languageService.getOutliningSpans(fileName); }); }; LanguageServiceShimObject.prototype.getTodoComments = function (fileName, descriptors) { var _this = this; return this.forwardJSONCall("getTodoComments('".concat(fileName, "')"), function () { return _this.languageService.getTodoComments(fileName, JSON.parse(descriptors)); }); }; /// CALL HIERARCHY LanguageServiceShimObject.prototype.prepareCallHierarchy = function (fileName, position) { var _this = this; return this.forwardJSONCall("prepareCallHierarchy('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.prepareCallHierarchy(fileName, position); }); }; LanguageServiceShimObject.prototype.provideCallHierarchyIncomingCalls = function (fileName, position) { var _this = this; return this.forwardJSONCall("provideCallHierarchyIncomingCalls('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.provideCallHierarchyIncomingCalls(fileName, position); }); }; LanguageServiceShimObject.prototype.provideCallHierarchyOutgoingCalls = function (fileName, position) { var _this = this; return this.forwardJSONCall("provideCallHierarchyOutgoingCalls('".concat(fileName, "', ").concat(position, ")"), function () { return _this.languageService.provideCallHierarchyOutgoingCalls(fileName, position); }); }; LanguageServiceShimObject.prototype.provideInlayHints = function (fileName, span, preference) { var _this = this; return this.forwardJSONCall("provideInlayHints('".concat(fileName, "', '").concat(JSON.stringify(span), "', ").concat(JSON.stringify(preference), ")"), function () { return _this.languageService.provideInlayHints(fileName, span, preference); }); }; /// Emit LanguageServiceShimObject.prototype.getEmitOutput = function (fileName) { var _this = this; return this.forwardJSONCall("getEmitOutput('".concat(fileName, "')"), function () { var _a = _this.languageService.getEmitOutput(fileName), diagnostics = _a.diagnostics, rest = __rest(_a, ["diagnostics"]); return __assign(__assign({}, rest), { diagnostics: _this.realizeDiagnostics(diagnostics) }); }); }; LanguageServiceShimObject.prototype.getEmitOutputObject = function (fileName) { var _this = this; return forwardCall(this.logger, "getEmitOutput('".concat(fileName, "')"), /*returnJson*/ false, function () { return _this.languageService.getEmitOutput(fileName); }, this.logPerformance); }; LanguageServiceShimObject.prototype.toggleLineComment = function (fileName, textRange) { var _this = this; return this.forwardJSONCall("toggleLineComment('".concat(fileName, "', '").concat(JSON.stringify(textRange), "')"), function () { return _this.languageService.toggleLineComment(fileName, textRange); }); }; LanguageServiceShimObject.prototype.toggleMultilineComment = function (fileName, textRange) { var _this = this; return this.forwardJSONCall("toggleMultilineComment('".concat(fileName, "', '").concat(JSON.stringify(textRange), "')"), function () { return _this.languageService.toggleMultilineComment(fileName, textRange); }); }; LanguageServiceShimObject.prototype.commentSelection = function (fileName, textRange) { var _this = this; return this.forwardJSONCall("commentSelection('".concat(fileName, "', '").concat(JSON.stringify(textRange), "')"), function () { return _this.languageService.commentSelection(fileName, textRange); }); }; LanguageServiceShimObject.prototype.uncommentSelection = function (fileName, textRange) { var _this = this; return this.forwardJSONCall("uncommentSelection('".concat(fileName, "', '").concat(JSON.stringify(textRange), "')"), function () { return _this.languageService.uncommentSelection(fileName, textRange); }); }; return LanguageServiceShimObject; }(ShimBase)); function convertClassifications(classifications) { return { spans: classifications.spans.join(","), endOfLineState: classifications.endOfLineState }; } var ClassifierShimObject = /** @class */ (function (_super) { __extends(ClassifierShimObject, _super); function ClassifierShimObject(factory, logger) { var _this = _super.call(this, factory) || this; _this.logger = logger; _this.logPerformance = false; _this.classifier = ts.createClassifier(); return _this; } ClassifierShimObject.prototype.getEncodedLexicalClassifications = function (text, lexState, syntacticClassifierAbsent) { var _this = this; if (syntacticClassifierAbsent === void 0) { syntacticClassifierAbsent = false; } return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", function () { return convertClassifications(_this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)); }, this.logPerformance); }; /// COLORIZATION ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) { if (classifyKeywordsInGenerics === void 0) { classifyKeywordsInGenerics = false; } var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics); var result = ""; for (var _i = 0, _a = classification.entries; _i < _a.length; _i++) { var item = _a[_i]; result += item.length + "\n"; result += item.classification + "\n"; } result += classification.finalLexState; return result; }; return ClassifierShimObject; }(ShimBase)); var CoreServicesShimObject = /** @class */ (function (_super) { __extends(CoreServicesShimObject, _super); function CoreServicesShimObject(factory, logger, host) { var _this = _super.call(this, factory) || this; _this.logger = logger; _this.host = host; _this.logPerformance = false; return _this; } CoreServicesShimObject.prototype.forwardJSONCall = function (actionDescription, action) { return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance); }; CoreServicesShimObject.prototype.resolveModuleName = function (fileName, moduleName, compilerOptionsJson) { var _this = this; return this.forwardJSONCall("resolveModuleName('".concat(fileName, "')"), function () { var compilerOptions = JSON.parse(compilerOptionsJson); var result = ts.resolveModuleName(moduleName, ts.normalizeSlashes(fileName), compilerOptions, _this.host); var resolvedFileName = result.resolvedModule ? result.resolvedModule.resolvedFileName : undefined; if (result.resolvedModule && result.resolvedModule.extension !== ".ts" /* Extension.Ts */ && result.resolvedModule.extension !== ".tsx" /* Extension.Tsx */ && result.resolvedModule.extension !== ".d.ts" /* Extension.Dts */) { resolvedFileName = undefined; } return { resolvedFileName: resolvedFileName, failedLookupLocations: result.failedLookupLocations }; }); }; CoreServicesShimObject.prototype.resolveTypeReferenceDirective = function (fileName, typeReferenceDirective, compilerOptionsJson) { var _this = this; return this.forwardJSONCall("resolveTypeReferenceDirective(".concat(fileName, ")"), function () { var compilerOptions = JSON.parse(compilerOptionsJson); var result = ts.resolveTypeReferenceDirective(typeReferenceDirective, ts.normalizeSlashes(fileName), compilerOptions, _this.host); return { resolvedFileName: result.resolvedTypeReferenceDirective ? result.resolvedTypeReferenceDirective.resolvedFileName : undefined, primary: result.resolvedTypeReferenceDirective ? result.resolvedTypeReferenceDirective.primary : true, failedLookupLocations: result.failedLookupLocations }; }); }; CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) { var _this = this; return this.forwardJSONCall("getPreProcessedFileInfo('".concat(fileName, "')"), function () { // for now treat files as JavaScript var result = ts.preProcessFile(ts.getSnapshotText(sourceTextSnapshot), /* readImportFiles */ true, /* detectJavaScriptImports */ true); return { referencedFiles: _this.convertFileReferences(result.referencedFiles), importedFiles: _this.convertFileReferences(result.importedFiles), ambientExternalModules: result.ambientExternalModules, isLibFile: result.isLibFile, typeReferenceDirectives: _this.convertFileReferences(result.typeReferenceDirectives), libReferenceDirectives: _this.convertFileReferences(result.libReferenceDirectives) }; }); }; CoreServicesShimObject.prototype.getAutomaticTypeDirectiveNames = function (compilerOptionsJson) { var _this = this; return this.forwardJSONCall("getAutomaticTypeDirectiveNames('".concat(compilerOptionsJson, "')"), function () { var compilerOptions = JSON.parse(compilerOptionsJson); return ts.getAutomaticTypeDirectiveNames(compilerOptions, _this.host); }); }; CoreServicesShimObject.prototype.convertFileReferences = function (refs) { if (!refs) { return undefined; } var result = []; for (var _i = 0, refs_1 = refs; _i < refs_1.length; _i++) { var ref = refs_1[_i]; result.push({ path: ts.normalizeSlashes(ref.fileName), position: ref.pos, length: ref.end - ref.pos }); } return result; }; CoreServicesShimObject.prototype.getTSConfigFileInfo = function (fileName, sourceTextSnapshot) { var _this = this; return this.forwardJSONCall("getTSConfigFileInfo('".concat(fileName, "')"), function () { var result = ts.parseJsonText(fileName, ts.getSnapshotText(sourceTextSnapshot)); var normalizedFileName = ts.normalizeSlashes(fileName); var configFile = ts.parseJsonSourceFileConfigFileContent(result, _this.host, ts.getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName); return { options: configFile.options, typeAcquisition: configFile.typeAcquisition, files: configFile.fileNames, raw: configFile.raw, errors: realizeDiagnostics(__spreadArray(__spreadArray([], result.parseDiagnostics, true), configFile.errors, true), "\r\n") }; }); }; CoreServicesShimObject.prototype.getDefaultCompilationSettings = function () { return this.forwardJSONCall("getDefaultCompilationSettings()", function () { return ts.getDefaultCompilerOptions(); }); }; CoreServicesShimObject.prototype.discoverTypings = function (discoverTypingsJson) { var _this = this; var getCanonicalFileName = ts.createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false); return this.forwardJSONCall("discoverTypings()", function () { var info = JSON.parse(discoverTypingsJson); if (_this.safeList === undefined) { _this.safeList = ts.JsTyping.loadSafeList(_this.host, ts.toPath(info.safeListPath, info.safeListPath, getCanonicalFileName)); } return ts.JsTyping.discoverTypings(_this.host, function (msg) { return _this.logger.log(msg); }, info.fileNames, ts.toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName), _this.safeList, info.packageNameToTypingLocation, info.typeAcquisition, info.unresolvedImports, info.typesRegistry); }); }; return CoreServicesShimObject; }(ShimBase)); var TypeScriptServicesFactory = /** @class */ (function () { function TypeScriptServicesFactory() { this._shims = []; } /* * Returns script API version. */ TypeScriptServicesFactory.prototype.getServicesVersion = function () { return ts.servicesVersion; }; TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) { try { if (this.documentRegistry === undefined) { this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } var hostAdapter = new LanguageServiceShimHostAdapter(host); var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry, /*syntaxOnly*/ false); return new LanguageServiceShimObject(this, host, languageService); } catch (err) { logInternalError(host, err); throw err; } }; TypeScriptServicesFactory.prototype.createClassifierShim = function (logger) { try { return new ClassifierShimObject(this, logger); } catch (err) { logInternalError(logger, err); throw err; } }; TypeScriptServicesFactory.prototype.createCoreServicesShim = function (host) { try { var adapter = new CoreServicesShimHostAdapter(host); return new CoreServicesShimObject(this, host, adapter); } catch (err) { logInternalError(host, err); throw err; } }; TypeScriptServicesFactory.prototype.close = function () { // Forget all the registered shims ts.clear(this._shims); this.documentRegistry = undefined; }; TypeScriptServicesFactory.prototype.registerShim = function (shim) { this._shims.push(shim); }; TypeScriptServicesFactory.prototype.unregisterShim = function (shim) { for (var i = 0; i < this._shims.length; i++) { if (this._shims[i] === shim) { delete this._shims[i]; return; } } throw new Error("Invalid operation"); }; return TypeScriptServicesFactory; }()); ts.TypeScriptServicesFactory = TypeScriptServicesFactory; })(ts || (ts = {})); /* eslint-enable no-in-operator */ // We polyfill `globalThis` here so re can reliably patch the global scope // in the contexts we want to in the same way across script and module formats /* eslint-enable no-var */ ((function () { if (typeof globalThis === "object") return; try { Object.defineProperty(Object.prototype, "__magic__", { get: function () { return this; }, configurable: true }); //@ts-ignore __magic__.globalThis = __magic__; // The previous line should have made `globalThis` globally // available, but it fails in Internet Explorer 10 and older. // Detect this failure and fall back. if (typeof globalThis === "undefined") { // Assume `window` exists. //@ts-ignore window.globalThis = window; } //@ts-ignore delete Object.prototype.__magic__; } catch (error) { // In IE8, Object.defineProperty only works on DOM objects. // If we hit this code path, assume `window` exists. //@ts-ignore window.globalThis = window; } })()); // #endregion The polyfill ends here. // if `process` is undefined, we're probably not running in node - patch legacy members onto the global scope // @ts-ignore if (typeof process === "undefined" || process.browser) { /// TODO: this is used by VS, clean this up on both sides of the interface //@ts-ignore globalThis.TypeScript = globalThis.TypeScript || {}; //@ts-ignore globalThis.TypeScript.Services = globalThis.TypeScript.Services || {}; //@ts-ignore globalThis.TypeScript.Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory; // 'toolsVersion' gets consumed by the managed side, so it's not unused. // TODO: it should be moved into a namespace though. //@ts-ignore globalThis.toolsVersion = ts.versionMajorMinor; } if (typeof module !== "undefined" && module.exports) { module.exports = ts; } var ts; (function (ts) { // The following are deprecations for the public API. Deprecated exports are removed from the compiler itself // and compatible implementations are added here, along with an appropriate deprecation warning using // the `@deprecated` JSDoc tag as well as the `Debug.deprecate` API. // // Deprecations fall into one of three categories: // // * "soft" - Soft deprecations are indicated with the `@deprecated` JSDoc Tag. // * "warn" - Warning deprecations are indicated with the `@deprecated` JSDoc Tag and a diagnostic message (assuming a compatible host) // * "error" - Error deprecations are indicated with the `@deprecated` JSDoc tag and will throw a `TypeError` when invoked. // DEPRECATION: Node factory top-level exports // DEPRECATION PLAN: // - soft: 4.0 // - warn: 4.1 // - error: TBD // #region Node factory top-level exports // NOTE: These exports are deprecated in favor of using a `NodeFactory` instance and exist here purely for backwards compatibility reasons. var factoryDeprecation = { since: "4.0", warnAfter: "4.1", message: "Use the appropriate method on 'ts.factory' or the 'factory' supplied by your transformation context instead." }; /** @deprecated Use `factory.createNodeArray` or the factory supplied by your transformation context instead. */ ts.createNodeArray = ts.Debug.deprecate(ts.factory.createNodeArray, factoryDeprecation); /** @deprecated Use `factory.createNumericLiteral` or the factory supplied by your transformation context instead. */ ts.createNumericLiteral = ts.Debug.deprecate(ts.factory.createNumericLiteral, factoryDeprecation); /** @deprecated Use `factory.createBigIntLiteral` or the factory supplied by your transformation context instead. */ ts.createBigIntLiteral = ts.Debug.deprecate(ts.factory.createBigIntLiteral, factoryDeprecation); /** @deprecated Use `factory.createStringLiteral` or the factory supplied by your transformation context instead. */ ts.createStringLiteral = ts.Debug.deprecate(ts.factory.createStringLiteral, factoryDeprecation); /** @deprecated Use `factory.createStringLiteralFromNode` or the factory supplied by your transformation context instead. */ ts.createStringLiteralFromNode = ts.Debug.deprecate(ts.factory.createStringLiteralFromNode, factoryDeprecation); /** @deprecated Use `factory.createRegularExpressionLiteral` or the factory supplied by your transformation context instead. */ ts.createRegularExpressionLiteral = ts.Debug.deprecate(ts.factory.createRegularExpressionLiteral, factoryDeprecation); /** @deprecated Use `factory.createLoopVariable` or the factory supplied by your transformation context instead. */ ts.createLoopVariable = ts.Debug.deprecate(ts.factory.createLoopVariable, factoryDeprecation); /** @deprecated Use `factory.createUniqueName` or the factory supplied by your transformation context instead. */ ts.createUniqueName = ts.Debug.deprecate(ts.factory.createUniqueName, factoryDeprecation); /** @deprecated Use `factory.createPrivateIdentifier` or the factory supplied by your transformation context instead. */ ts.createPrivateIdentifier = ts.Debug.deprecate(ts.factory.createPrivateIdentifier, factoryDeprecation); /** @deprecated Use `factory.createSuper` or the factory supplied by your transformation context instead. */ ts.createSuper = ts.Debug.deprecate(ts.factory.createSuper, factoryDeprecation); /** @deprecated Use `factory.createThis` or the factory supplied by your transformation context instead. */ ts.createThis = ts.Debug.deprecate(ts.factory.createThis, factoryDeprecation); /** @deprecated Use `factory.createNull` or the factory supplied by your transformation context instead. */ ts.createNull = ts.Debug.deprecate(ts.factory.createNull, factoryDeprecation); /** @deprecated Use `factory.createTrue` or the factory supplied by your transformation context instead. */ ts.createTrue = ts.Debug.deprecate(ts.factory.createTrue, factoryDeprecation); /** @deprecated Use `factory.createFalse` or the factory supplied by your transformation context instead. */ ts.createFalse = ts.Debug.deprecate(ts.factory.createFalse, factoryDeprecation); /** @deprecated Use `factory.createModifier` or the factory supplied by your transformation context instead. */ ts.createModifier = ts.Debug.deprecate(ts.factory.createModifier, factoryDeprecation); /** @deprecated Use `factory.createModifiersFromModifierFlags` or the factory supplied by your transformation context instead. */ ts.createModifiersFromModifierFlags = ts.Debug.deprecate(ts.factory.createModifiersFromModifierFlags, factoryDeprecation); /** @deprecated Use `factory.createQualifiedName` or the factory supplied by your transformation context instead. */ ts.createQualifiedName = ts.Debug.deprecate(ts.factory.createQualifiedName, factoryDeprecation); /** @deprecated Use `factory.updateQualifiedName` or the factory supplied by your transformation context instead. */ ts.updateQualifiedName = ts.Debug.deprecate(ts.factory.updateQualifiedName, factoryDeprecation); /** @deprecated Use `factory.createComputedPropertyName` or the factory supplied by your transformation context instead. */ ts.createComputedPropertyName = ts.Debug.deprecate(ts.factory.createComputedPropertyName, factoryDeprecation); /** @deprecated Use `factory.updateComputedPropertyName` or the factory supplied by your transformation context instead. */ ts.updateComputedPropertyName = ts.Debug.deprecate(ts.factory.updateComputedPropertyName, factoryDeprecation); /** @deprecated Use `factory.createTypeParameterDeclaration` or the factory supplied by your transformation context instead. */ ts.createTypeParameterDeclaration = ts.Debug.deprecate(ts.factory.createTypeParameterDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateTypeParameterDeclaration` or the factory supplied by your transformation context instead. */ ts.updateTypeParameterDeclaration = ts.Debug.deprecate(ts.factory.updateTypeParameterDeclaration, factoryDeprecation); /** @deprecated Use `factory.createParameterDeclaration` or the factory supplied by your transformation context instead. */ ts.createParameter = ts.Debug.deprecate(ts.factory.createParameterDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateParameterDeclaration` or the factory supplied by your transformation context instead. */ ts.updateParameter = ts.Debug.deprecate(ts.factory.updateParameterDeclaration, factoryDeprecation); /** @deprecated Use `factory.createDecorator` or the factory supplied by your transformation context instead. */ ts.createDecorator = ts.Debug.deprecate(ts.factory.createDecorator, factoryDeprecation); /** @deprecated Use `factory.updateDecorator` or the factory supplied by your transformation context instead. */ ts.updateDecorator = ts.Debug.deprecate(ts.factory.updateDecorator, factoryDeprecation); /** @deprecated Use `factory.createPropertyDeclaration` or the factory supplied by your transformation context instead. */ ts.createProperty = ts.Debug.deprecate(ts.factory.createPropertyDeclaration, factoryDeprecation); /** @deprecated Use `factory.updatePropertyDeclaration` or the factory supplied by your transformation context instead. */ ts.updateProperty = ts.Debug.deprecate(ts.factory.updatePropertyDeclaration, factoryDeprecation); /** @deprecated Use `factory.createMethodDeclaration` or the factory supplied by your transformation context instead. */ ts.createMethod = ts.Debug.deprecate(ts.factory.createMethodDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateMethodDeclaration` or the factory supplied by your transformation context instead. */ ts.updateMethod = ts.Debug.deprecate(ts.factory.updateMethodDeclaration, factoryDeprecation); /** @deprecated Use `factory.createConstructorDeclaration` or the factory supplied by your transformation context instead. */ ts.createConstructor = ts.Debug.deprecate(ts.factory.createConstructorDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateConstructorDeclaration` or the factory supplied by your transformation context instead. */ ts.updateConstructor = ts.Debug.deprecate(ts.factory.updateConstructorDeclaration, factoryDeprecation); /** @deprecated Use `factory.createGetAccessorDeclaration` or the factory supplied by your transformation context instead. */ ts.createGetAccessor = ts.Debug.deprecate(ts.factory.createGetAccessorDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateGetAccessorDeclaration` or the factory supplied by your transformation context instead. */ ts.updateGetAccessor = ts.Debug.deprecate(ts.factory.updateGetAccessorDeclaration, factoryDeprecation); /** @deprecated Use `factory.createSetAccessorDeclaration` or the factory supplied by your transformation context instead. */ ts.createSetAccessor = ts.Debug.deprecate(ts.factory.createSetAccessorDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateSetAccessorDeclaration` or the factory supplied by your transformation context instead. */ ts.updateSetAccessor = ts.Debug.deprecate(ts.factory.updateSetAccessorDeclaration, factoryDeprecation); /** @deprecated Use `factory.createCallSignature` or the factory supplied by your transformation context instead. */ ts.createCallSignature = ts.Debug.deprecate(ts.factory.createCallSignature, factoryDeprecation); /** @deprecated Use `factory.updateCallSignature` or the factory supplied by your transformation context instead. */ ts.updateCallSignature = ts.Debug.deprecate(ts.factory.updateCallSignature, factoryDeprecation); /** @deprecated Use `factory.createConstructSignature` or the factory supplied by your transformation context instead. */ ts.createConstructSignature = ts.Debug.deprecate(ts.factory.createConstructSignature, factoryDeprecation); /** @deprecated Use `factory.updateConstructSignature` or the factory supplied by your transformation context instead. */ ts.updateConstructSignature = ts.Debug.deprecate(ts.factory.updateConstructSignature, factoryDeprecation); /** @deprecated Use `factory.updateIndexSignature` or the factory supplied by your transformation context instead. */ ts.updateIndexSignature = ts.Debug.deprecate(ts.factory.updateIndexSignature, factoryDeprecation); /** @deprecated Use `factory.createKeywordTypeNode` or the factory supplied by your transformation context instead. */ ts.createKeywordTypeNode = ts.Debug.deprecate(ts.factory.createKeywordTypeNode, factoryDeprecation); /** @deprecated Use `factory.createTypePredicateNode` or the factory supplied by your transformation context instead. */ ts.createTypePredicateNodeWithModifier = ts.Debug.deprecate(ts.factory.createTypePredicateNode, factoryDeprecation); /** @deprecated Use `factory.updateTypePredicateNode` or the factory supplied by your transformation context instead. */ ts.updateTypePredicateNodeWithModifier = ts.Debug.deprecate(ts.factory.updateTypePredicateNode, factoryDeprecation); /** @deprecated Use `factory.createTypeReferenceNode` or the factory supplied by your transformation context instead. */ ts.createTypeReferenceNode = ts.Debug.deprecate(ts.factory.createTypeReferenceNode, factoryDeprecation); /** @deprecated Use `factory.updateTypeReferenceNode` or the factory supplied by your transformation context instead. */ ts.updateTypeReferenceNode = ts.Debug.deprecate(ts.factory.updateTypeReferenceNode, factoryDeprecation); /** @deprecated Use `factory.createFunctionTypeNode` or the factory supplied by your transformation context instead. */ ts.createFunctionTypeNode = ts.Debug.deprecate(ts.factory.createFunctionTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateFunctionTypeNode` or the factory supplied by your transformation context instead. */ ts.updateFunctionTypeNode = ts.Debug.deprecate(ts.factory.updateFunctionTypeNode, factoryDeprecation); /** @deprecated Use `factory.createConstructorTypeNode` or the factory supplied by your transformation context instead. */ ts.createConstructorTypeNode = ts.Debug.deprecate(function (typeParameters, parameters, type) { return ts.factory.createConstructorTypeNode(/*modifiers*/ undefined, typeParameters, parameters, type); }, factoryDeprecation); /** @deprecated Use `factory.updateConstructorTypeNode` or the factory supplied by your transformation context instead. */ ts.updateConstructorTypeNode = ts.Debug.deprecate(function (node, typeParameters, parameters, type) { return ts.factory.updateConstructorTypeNode(node, node.modifiers, typeParameters, parameters, type); }, factoryDeprecation); /** @deprecated Use `factory.createTypeQueryNode` or the factory supplied by your transformation context instead. */ ts.createTypeQueryNode = ts.Debug.deprecate(ts.factory.createTypeQueryNode, factoryDeprecation); /** @deprecated Use `factory.updateTypeQueryNode` or the factory supplied by your transformation context instead. */ ts.updateTypeQueryNode = ts.Debug.deprecate(ts.factory.updateTypeQueryNode, factoryDeprecation); /** @deprecated Use `factory.createTypeLiteralNode` or the factory supplied by your transformation context instead. */ ts.createTypeLiteralNode = ts.Debug.deprecate(ts.factory.createTypeLiteralNode, factoryDeprecation); /** @deprecated Use `factory.updateTypeLiteralNode` or the factory supplied by your transformation context instead. */ ts.updateTypeLiteralNode = ts.Debug.deprecate(ts.factory.updateTypeLiteralNode, factoryDeprecation); /** @deprecated Use `factory.createArrayTypeNode` or the factory supplied by your transformation context instead. */ ts.createArrayTypeNode = ts.Debug.deprecate(ts.factory.createArrayTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateArrayTypeNode` or the factory supplied by your transformation context instead. */ ts.updateArrayTypeNode = ts.Debug.deprecate(ts.factory.updateArrayTypeNode, factoryDeprecation); /** @deprecated Use `factory.createTupleTypeNode` or the factory supplied by your transformation context instead. */ ts.createTupleTypeNode = ts.Debug.deprecate(ts.factory.createTupleTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateTupleTypeNode` or the factory supplied by your transformation context instead. */ ts.updateTupleTypeNode = ts.Debug.deprecate(ts.factory.updateTupleTypeNode, factoryDeprecation); /** @deprecated Use `factory.createOptionalTypeNode` or the factory supplied by your transformation context instead. */ ts.createOptionalTypeNode = ts.Debug.deprecate(ts.factory.createOptionalTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateOptionalTypeNode` or the factory supplied by your transformation context instead. */ ts.updateOptionalTypeNode = ts.Debug.deprecate(ts.factory.updateOptionalTypeNode, factoryDeprecation); /** @deprecated Use `factory.createRestTypeNode` or the factory supplied by your transformation context instead. */ ts.createRestTypeNode = ts.Debug.deprecate(ts.factory.createRestTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateRestTypeNode` or the factory supplied by your transformation context instead. */ ts.updateRestTypeNode = ts.Debug.deprecate(ts.factory.updateRestTypeNode, factoryDeprecation); /** @deprecated Use `factory.createUnionTypeNode` or the factory supplied by your transformation context instead. */ ts.createUnionTypeNode = ts.Debug.deprecate(ts.factory.createUnionTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateUnionTypeNode` or the factory supplied by your transformation context instead. */ ts.updateUnionTypeNode = ts.Debug.deprecate(ts.factory.updateUnionTypeNode, factoryDeprecation); /** @deprecated Use `factory.createIntersectionTypeNode` or the factory supplied by your transformation context instead. */ ts.createIntersectionTypeNode = ts.Debug.deprecate(ts.factory.createIntersectionTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateIntersectionTypeNode` or the factory supplied by your transformation context instead. */ ts.updateIntersectionTypeNode = ts.Debug.deprecate(ts.factory.updateIntersectionTypeNode, factoryDeprecation); /** @deprecated Use `factory.createConditionalTypeNode` or the factory supplied by your transformation context instead. */ ts.createConditionalTypeNode = ts.Debug.deprecate(ts.factory.createConditionalTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateConditionalTypeNode` or the factory supplied by your transformation context instead. */ ts.updateConditionalTypeNode = ts.Debug.deprecate(ts.factory.updateConditionalTypeNode, factoryDeprecation); /** @deprecated Use `factory.createInferTypeNode` or the factory supplied by your transformation context instead. */ ts.createInferTypeNode = ts.Debug.deprecate(ts.factory.createInferTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateInferTypeNode` or the factory supplied by your transformation context instead. */ ts.updateInferTypeNode = ts.Debug.deprecate(ts.factory.updateInferTypeNode, factoryDeprecation); /** @deprecated Use `factory.createImportTypeNode` or the factory supplied by your transformation context instead. */ ts.createImportTypeNode = ts.Debug.deprecate(ts.factory.createImportTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateImportTypeNode` or the factory supplied by your transformation context instead. */ ts.updateImportTypeNode = ts.Debug.deprecate(ts.factory.updateImportTypeNode, factoryDeprecation); /** @deprecated Use `factory.createParenthesizedType` or the factory supplied by your transformation context instead. */ ts.createParenthesizedType = ts.Debug.deprecate(ts.factory.createParenthesizedType, factoryDeprecation); /** @deprecated Use `factory.updateParenthesizedType` or the factory supplied by your transformation context instead. */ ts.updateParenthesizedType = ts.Debug.deprecate(ts.factory.updateParenthesizedType, factoryDeprecation); /** @deprecated Use `factory.createThisTypeNode` or the factory supplied by your transformation context instead. */ ts.createThisTypeNode = ts.Debug.deprecate(ts.factory.createThisTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateTypeOperatorNode` or the factory supplied by your transformation context instead. */ ts.updateTypeOperatorNode = ts.Debug.deprecate(ts.factory.updateTypeOperatorNode, factoryDeprecation); /** @deprecated Use `factory.createIndexedAccessTypeNode` or the factory supplied by your transformation context instead. */ ts.createIndexedAccessTypeNode = ts.Debug.deprecate(ts.factory.createIndexedAccessTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateIndexedAccessTypeNode` or the factory supplied by your transformation context instead. */ ts.updateIndexedAccessTypeNode = ts.Debug.deprecate(ts.factory.updateIndexedAccessTypeNode, factoryDeprecation); /** @deprecated Use `factory.createMappedTypeNode` or the factory supplied by your transformation context instead. */ ts.createMappedTypeNode = ts.Debug.deprecate(ts.factory.createMappedTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateMappedTypeNode` or the factory supplied by your transformation context instead. */ ts.updateMappedTypeNode = ts.Debug.deprecate(ts.factory.updateMappedTypeNode, factoryDeprecation); /** @deprecated Use `factory.createLiteralTypeNode` or the factory supplied by your transformation context instead. */ ts.createLiteralTypeNode = ts.Debug.deprecate(ts.factory.createLiteralTypeNode, factoryDeprecation); /** @deprecated Use `factory.updateLiteralTypeNode` or the factory supplied by your transformation context instead. */ ts.updateLiteralTypeNode = ts.Debug.deprecate(ts.factory.updateLiteralTypeNode, factoryDeprecation); /** @deprecated Use `factory.createObjectBindingPattern` or the factory supplied by your transformation context instead. */ ts.createObjectBindingPattern = ts.Debug.deprecate(ts.factory.createObjectBindingPattern, factoryDeprecation); /** @deprecated Use `factory.updateObjectBindingPattern` or the factory supplied by your transformation context instead. */ ts.updateObjectBindingPattern = ts.Debug.deprecate(ts.factory.updateObjectBindingPattern, factoryDeprecation); /** @deprecated Use `factory.createArrayBindingPattern` or the factory supplied by your transformation context instead. */ ts.createArrayBindingPattern = ts.Debug.deprecate(ts.factory.createArrayBindingPattern, factoryDeprecation); /** @deprecated Use `factory.updateArrayBindingPattern` or the factory supplied by your transformation context instead. */ ts.updateArrayBindingPattern = ts.Debug.deprecate(ts.factory.updateArrayBindingPattern, factoryDeprecation); /** @deprecated Use `factory.createBindingElement` or the factory supplied by your transformation context instead. */ ts.createBindingElement = ts.Debug.deprecate(ts.factory.createBindingElement, factoryDeprecation); /** @deprecated Use `factory.updateBindingElement` or the factory supplied by your transformation context instead. */ ts.updateBindingElement = ts.Debug.deprecate(ts.factory.updateBindingElement, factoryDeprecation); /** @deprecated Use `factory.createArrayLiteralExpression` or the factory supplied by your transformation context instead. */ ts.createArrayLiteral = ts.Debug.deprecate(ts.factory.createArrayLiteralExpression, factoryDeprecation); /** @deprecated Use `factory.updateArrayLiteralExpression` or the factory supplied by your transformation context instead. */ ts.updateArrayLiteral = ts.Debug.deprecate(ts.factory.updateArrayLiteralExpression, factoryDeprecation); /** @deprecated Use `factory.createObjectLiteralExpression` or the factory supplied by your transformation context instead. */ ts.createObjectLiteral = ts.Debug.deprecate(ts.factory.createObjectLiteralExpression, factoryDeprecation); /** @deprecated Use `factory.updateObjectLiteralExpression` or the factory supplied by your transformation context instead. */ ts.updateObjectLiteral = ts.Debug.deprecate(ts.factory.updateObjectLiteralExpression, factoryDeprecation); /** @deprecated Use `factory.createPropertyAccessExpression` or the factory supplied by your transformation context instead. */ ts.createPropertyAccess = ts.Debug.deprecate(ts.factory.createPropertyAccessExpression, factoryDeprecation); /** @deprecated Use `factory.updatePropertyAccessExpression` or the factory supplied by your transformation context instead. */ ts.updatePropertyAccess = ts.Debug.deprecate(ts.factory.updatePropertyAccessExpression, factoryDeprecation); /** @deprecated Use `factory.createPropertyAccessChain` or the factory supplied by your transformation context instead. */ ts.createPropertyAccessChain = ts.Debug.deprecate(ts.factory.createPropertyAccessChain, factoryDeprecation); /** @deprecated Use `factory.updatePropertyAccessChain` or the factory supplied by your transformation context instead. */ ts.updatePropertyAccessChain = ts.Debug.deprecate(ts.factory.updatePropertyAccessChain, factoryDeprecation); /** @deprecated Use `factory.createElementAccessExpression` or the factory supplied by your transformation context instead. */ ts.createElementAccess = ts.Debug.deprecate(ts.factory.createElementAccessExpression, factoryDeprecation); /** @deprecated Use `factory.updateElementAccessExpression` or the factory supplied by your transformation context instead. */ ts.updateElementAccess = ts.Debug.deprecate(ts.factory.updateElementAccessExpression, factoryDeprecation); /** @deprecated Use `factory.createElementAccessChain` or the factory supplied by your transformation context instead. */ ts.createElementAccessChain = ts.Debug.deprecate(ts.factory.createElementAccessChain, factoryDeprecation); /** @deprecated Use `factory.updateElementAccessChain` or the factory supplied by your transformation context instead. */ ts.updateElementAccessChain = ts.Debug.deprecate(ts.factory.updateElementAccessChain, factoryDeprecation); /** @deprecated Use `factory.createCallExpression` or the factory supplied by your transformation context instead. */ ts.createCall = ts.Debug.deprecate(ts.factory.createCallExpression, factoryDeprecation); /** @deprecated Use `factory.updateCallExpression` or the factory supplied by your transformation context instead. */ ts.updateCall = ts.Debug.deprecate(ts.factory.updateCallExpression, factoryDeprecation); /** @deprecated Use `factory.createCallChain` or the factory supplied by your transformation context instead. */ ts.createCallChain = ts.Debug.deprecate(ts.factory.createCallChain, factoryDeprecation); /** @deprecated Use `factory.updateCallChain` or the factory supplied by your transformation context instead. */ ts.updateCallChain = ts.Debug.deprecate(ts.factory.updateCallChain, factoryDeprecation); /** @deprecated Use `factory.createNewExpression` or the factory supplied by your transformation context instead. */ ts.createNew = ts.Debug.deprecate(ts.factory.createNewExpression, factoryDeprecation); /** @deprecated Use `factory.updateNewExpression` or the factory supplied by your transformation context instead. */ ts.updateNew = ts.Debug.deprecate(ts.factory.updateNewExpression, factoryDeprecation); /** @deprecated Use `factory.createTypeAssertion` or the factory supplied by your transformation context instead. */ ts.createTypeAssertion = ts.Debug.deprecate(ts.factory.createTypeAssertion, factoryDeprecation); /** @deprecated Use `factory.updateTypeAssertion` or the factory supplied by your transformation context instead. */ ts.updateTypeAssertion = ts.Debug.deprecate(ts.factory.updateTypeAssertion, factoryDeprecation); /** @deprecated Use `factory.createParenthesizedExpression` or the factory supplied by your transformation context instead. */ ts.createParen = ts.Debug.deprecate(ts.factory.createParenthesizedExpression, factoryDeprecation); /** @deprecated Use `factory.updateParenthesizedExpression` or the factory supplied by your transformation context instead. */ ts.updateParen = ts.Debug.deprecate(ts.factory.updateParenthesizedExpression, factoryDeprecation); /** @deprecated Use `factory.createFunctionExpression` or the factory supplied by your transformation context instead. */ ts.createFunctionExpression = ts.Debug.deprecate(ts.factory.createFunctionExpression, factoryDeprecation); /** @deprecated Use `factory.updateFunctionExpression` or the factory supplied by your transformation context instead. */ ts.updateFunctionExpression = ts.Debug.deprecate(ts.factory.updateFunctionExpression, factoryDeprecation); /** @deprecated Use `factory.createDeleteExpression` or the factory supplied by your transformation context instead. */ ts.createDelete = ts.Debug.deprecate(ts.factory.createDeleteExpression, factoryDeprecation); /** @deprecated Use `factory.updateDeleteExpression` or the factory supplied by your transformation context instead. */ ts.updateDelete = ts.Debug.deprecate(ts.factory.updateDeleteExpression, factoryDeprecation); /** @deprecated Use `factory.createTypeOfExpression` or the factory supplied by your transformation context instead. */ ts.createTypeOf = ts.Debug.deprecate(ts.factory.createTypeOfExpression, factoryDeprecation); /** @deprecated Use `factory.updateTypeOfExpression` or the factory supplied by your transformation context instead. */ ts.updateTypeOf = ts.Debug.deprecate(ts.factory.updateTypeOfExpression, factoryDeprecation); /** @deprecated Use `factory.createVoidExpression` or the factory supplied by your transformation context instead. */ ts.createVoid = ts.Debug.deprecate(ts.factory.createVoidExpression, factoryDeprecation); /** @deprecated Use `factory.updateVoidExpression` or the factory supplied by your transformation context instead. */ ts.updateVoid = ts.Debug.deprecate(ts.factory.updateVoidExpression, factoryDeprecation); /** @deprecated Use `factory.createAwaitExpression` or the factory supplied by your transformation context instead. */ ts.createAwait = ts.Debug.deprecate(ts.factory.createAwaitExpression, factoryDeprecation); /** @deprecated Use `factory.updateAwaitExpression` or the factory supplied by your transformation context instead. */ ts.updateAwait = ts.Debug.deprecate(ts.factory.updateAwaitExpression, factoryDeprecation); /** @deprecated Use `factory.createPrefixExpression` or the factory supplied by your transformation context instead. */ ts.createPrefix = ts.Debug.deprecate(ts.factory.createPrefixUnaryExpression, factoryDeprecation); /** @deprecated Use `factory.updatePrefixExpression` or the factory supplied by your transformation context instead. */ ts.updatePrefix = ts.Debug.deprecate(ts.factory.updatePrefixUnaryExpression, factoryDeprecation); /** @deprecated Use `factory.createPostfixUnaryExpression` or the factory supplied by your transformation context instead. */ ts.createPostfix = ts.Debug.deprecate(ts.factory.createPostfixUnaryExpression, factoryDeprecation); /** @deprecated Use `factory.updatePostfixUnaryExpression` or the factory supplied by your transformation context instead. */ ts.updatePostfix = ts.Debug.deprecate(ts.factory.updatePostfixUnaryExpression, factoryDeprecation); /** @deprecated Use `factory.createBinaryExpression` or the factory supplied by your transformation context instead. */ ts.createBinary = ts.Debug.deprecate(ts.factory.createBinaryExpression, factoryDeprecation); /** @deprecated Use `factory.updateConditionalExpression` or the factory supplied by your transformation context instead. */ ts.updateConditional = ts.Debug.deprecate(ts.factory.updateConditionalExpression, factoryDeprecation); /** @deprecated Use `factory.createTemplateExpression` or the factory supplied by your transformation context instead. */ ts.createTemplateExpression = ts.Debug.deprecate(ts.factory.createTemplateExpression, factoryDeprecation); /** @deprecated Use `factory.updateTemplateExpression` or the factory supplied by your transformation context instead. */ ts.updateTemplateExpression = ts.Debug.deprecate(ts.factory.updateTemplateExpression, factoryDeprecation); /** @deprecated Use `factory.createTemplateHead` or the factory supplied by your transformation context instead. */ ts.createTemplateHead = ts.Debug.deprecate(ts.factory.createTemplateHead, factoryDeprecation); /** @deprecated Use `factory.createTemplateMiddle` or the factory supplied by your transformation context instead. */ ts.createTemplateMiddle = ts.Debug.deprecate(ts.factory.createTemplateMiddle, factoryDeprecation); /** @deprecated Use `factory.createTemplateTail` or the factory supplied by your transformation context instead. */ ts.createTemplateTail = ts.Debug.deprecate(ts.factory.createTemplateTail, factoryDeprecation); /** @deprecated Use `factory.createNoSubstitutionTemplateLiteral` or the factory supplied by your transformation context instead. */ ts.createNoSubstitutionTemplateLiteral = ts.Debug.deprecate(ts.factory.createNoSubstitutionTemplateLiteral, factoryDeprecation); /** @deprecated Use `factory.updateYieldExpression` or the factory supplied by your transformation context instead. */ ts.updateYield = ts.Debug.deprecate(ts.factory.updateYieldExpression, factoryDeprecation); /** @deprecated Use `factory.createSpreadExpression` or the factory supplied by your transformation context instead. */ ts.createSpread = ts.Debug.deprecate(ts.factory.createSpreadElement, factoryDeprecation); /** @deprecated Use `factory.updateSpreadExpression` or the factory supplied by your transformation context instead. */ ts.updateSpread = ts.Debug.deprecate(ts.factory.updateSpreadElement, factoryDeprecation); /** @deprecated Use `factory.createOmittedExpression` or the factory supplied by your transformation context instead. */ ts.createOmittedExpression = ts.Debug.deprecate(ts.factory.createOmittedExpression, factoryDeprecation); /** @deprecated Use `factory.createAsExpression` or the factory supplied by your transformation context instead. */ ts.createAsExpression = ts.Debug.deprecate(ts.factory.createAsExpression, factoryDeprecation); /** @deprecated Use `factory.updateAsExpression` or the factory supplied by your transformation context instead. */ ts.updateAsExpression = ts.Debug.deprecate(ts.factory.updateAsExpression, factoryDeprecation); /** @deprecated Use `factory.createNonNullExpression` or the factory supplied by your transformation context instead. */ ts.createNonNullExpression = ts.Debug.deprecate(ts.factory.createNonNullExpression, factoryDeprecation); /** @deprecated Use `factory.updateNonNullExpression` or the factory supplied by your transformation context instead. */ ts.updateNonNullExpression = ts.Debug.deprecate(ts.factory.updateNonNullExpression, factoryDeprecation); /** @deprecated Use `factory.createNonNullChain` or the factory supplied by your transformation context instead. */ ts.createNonNullChain = ts.Debug.deprecate(ts.factory.createNonNullChain, factoryDeprecation); /** @deprecated Use `factory.updateNonNullChain` or the factory supplied by your transformation context instead. */ ts.updateNonNullChain = ts.Debug.deprecate(ts.factory.updateNonNullChain, factoryDeprecation); /** @deprecated Use `factory.createMetaProperty` or the factory supplied by your transformation context instead. */ ts.createMetaProperty = ts.Debug.deprecate(ts.factory.createMetaProperty, factoryDeprecation); /** @deprecated Use `factory.updateMetaProperty` or the factory supplied by your transformation context instead. */ ts.updateMetaProperty = ts.Debug.deprecate(ts.factory.updateMetaProperty, factoryDeprecation); /** @deprecated Use `factory.createTemplateSpan` or the factory supplied by your transformation context instead. */ ts.createTemplateSpan = ts.Debug.deprecate(ts.factory.createTemplateSpan, factoryDeprecation); /** @deprecated Use `factory.updateTemplateSpan` or the factory supplied by your transformation context instead. */ ts.updateTemplateSpan = ts.Debug.deprecate(ts.factory.updateTemplateSpan, factoryDeprecation); /** @deprecated Use `factory.createSemicolonClassElement` or the factory supplied by your transformation context instead. */ ts.createSemicolonClassElement = ts.Debug.deprecate(ts.factory.createSemicolonClassElement, factoryDeprecation); /** @deprecated Use `factory.createBlock` or the factory supplied by your transformation context instead. */ ts.createBlock = ts.Debug.deprecate(ts.factory.createBlock, factoryDeprecation); /** @deprecated Use `factory.updateBlock` or the factory supplied by your transformation context instead. */ ts.updateBlock = ts.Debug.deprecate(ts.factory.updateBlock, factoryDeprecation); /** @deprecated Use `factory.createVariableStatement` or the factory supplied by your transformation context instead. */ ts.createVariableStatement = ts.Debug.deprecate(ts.factory.createVariableStatement, factoryDeprecation); /** @deprecated Use `factory.updateVariableStatement` or the factory supplied by your transformation context instead. */ ts.updateVariableStatement = ts.Debug.deprecate(ts.factory.updateVariableStatement, factoryDeprecation); /** @deprecated Use `factory.createEmptyStatement` or the factory supplied by your transformation context instead. */ ts.createEmptyStatement = ts.Debug.deprecate(ts.factory.createEmptyStatement, factoryDeprecation); /** @deprecated Use `factory.createExpressionStatement` or the factory supplied by your transformation context instead. */ ts.createExpressionStatement = ts.Debug.deprecate(ts.factory.createExpressionStatement, factoryDeprecation); /** @deprecated Use `factory.updateExpressionStatement` or the factory supplied by your transformation context instead. */ ts.updateExpressionStatement = ts.Debug.deprecate(ts.factory.updateExpressionStatement, factoryDeprecation); /** @deprecated Use `factory.createExpressionStatement` or the factory supplied by your transformation context instead. */ ts.createStatement = ts.Debug.deprecate(ts.factory.createExpressionStatement, factoryDeprecation); /** @deprecated Use `factory.updateExpressionStatement` or the factory supplied by your transformation context instead. */ ts.updateStatement = ts.Debug.deprecate(ts.factory.updateExpressionStatement, factoryDeprecation); /** @deprecated Use `factory.createIfStatement` or the factory supplied by your transformation context instead. */ ts.createIf = ts.Debug.deprecate(ts.factory.createIfStatement, factoryDeprecation); /** @deprecated Use `factory.updateIfStatement` or the factory supplied by your transformation context instead. */ ts.updateIf = ts.Debug.deprecate(ts.factory.updateIfStatement, factoryDeprecation); /** @deprecated Use `factory.createDoStatement` or the factory supplied by your transformation context instead. */ ts.createDo = ts.Debug.deprecate(ts.factory.createDoStatement, factoryDeprecation); /** @deprecated Use `factory.updateDoStatement` or the factory supplied by your transformation context instead. */ ts.updateDo = ts.Debug.deprecate(ts.factory.updateDoStatement, factoryDeprecation); /** @deprecated Use `factory.createWhileStatement` or the factory supplied by your transformation context instead. */ ts.createWhile = ts.Debug.deprecate(ts.factory.createWhileStatement, factoryDeprecation); /** @deprecated Use `factory.updateWhileStatement` or the factory supplied by your transformation context instead. */ ts.updateWhile = ts.Debug.deprecate(ts.factory.updateWhileStatement, factoryDeprecation); /** @deprecated Use `factory.createForStatement` or the factory supplied by your transformation context instead. */ ts.createFor = ts.Debug.deprecate(ts.factory.createForStatement, factoryDeprecation); /** @deprecated Use `factory.updateForStatement` or the factory supplied by your transformation context instead. */ ts.updateFor = ts.Debug.deprecate(ts.factory.updateForStatement, factoryDeprecation); /** @deprecated Use `factory.createForInStatement` or the factory supplied by your transformation context instead. */ ts.createForIn = ts.Debug.deprecate(ts.factory.createForInStatement, factoryDeprecation); /** @deprecated Use `factory.updateForInStatement` or the factory supplied by your transformation context instead. */ ts.updateForIn = ts.Debug.deprecate(ts.factory.updateForInStatement, factoryDeprecation); /** @deprecated Use `factory.createForOfStatement` or the factory supplied by your transformation context instead. */ ts.createForOf = ts.Debug.deprecate(ts.factory.createForOfStatement, factoryDeprecation); /** @deprecated Use `factory.updateForOfStatement` or the factory supplied by your transformation context instead. */ ts.updateForOf = ts.Debug.deprecate(ts.factory.updateForOfStatement, factoryDeprecation); /** @deprecated Use `factory.createContinueStatement` or the factory supplied by your transformation context instead. */ ts.createContinue = ts.Debug.deprecate(ts.factory.createContinueStatement, factoryDeprecation); /** @deprecated Use `factory.updateContinueStatement` or the factory supplied by your transformation context instead. */ ts.updateContinue = ts.Debug.deprecate(ts.factory.updateContinueStatement, factoryDeprecation); /** @deprecated Use `factory.createBreakStatement` or the factory supplied by your transformation context instead. */ ts.createBreak = ts.Debug.deprecate(ts.factory.createBreakStatement, factoryDeprecation); /** @deprecated Use `factory.updateBreakStatement` or the factory supplied by your transformation context instead. */ ts.updateBreak = ts.Debug.deprecate(ts.factory.updateBreakStatement, factoryDeprecation); /** @deprecated Use `factory.createReturnStatement` or the factory supplied by your transformation context instead. */ ts.createReturn = ts.Debug.deprecate(ts.factory.createReturnStatement, factoryDeprecation); /** @deprecated Use `factory.updateReturnStatement` or the factory supplied by your transformation context instead. */ ts.updateReturn = ts.Debug.deprecate(ts.factory.updateReturnStatement, factoryDeprecation); /** @deprecated Use `factory.createWithStatement` or the factory supplied by your transformation context instead. */ ts.createWith = ts.Debug.deprecate(ts.factory.createWithStatement, factoryDeprecation); /** @deprecated Use `factory.updateWithStatement` or the factory supplied by your transformation context instead. */ ts.updateWith = ts.Debug.deprecate(ts.factory.updateWithStatement, factoryDeprecation); /** @deprecated Use `factory.createSwitchStatement` or the factory supplied by your transformation context instead. */ ts.createSwitch = ts.Debug.deprecate(ts.factory.createSwitchStatement, factoryDeprecation); /** @deprecated Use `factory.updateSwitchStatement` or the factory supplied by your transformation context instead. */ ts.updateSwitch = ts.Debug.deprecate(ts.factory.updateSwitchStatement, factoryDeprecation); /** @deprecated Use `factory.createLabelStatement` or the factory supplied by your transformation context instead. */ ts.createLabel = ts.Debug.deprecate(ts.factory.createLabeledStatement, factoryDeprecation); /** @deprecated Use `factory.updateLabelStatement` or the factory supplied by your transformation context instead. */ ts.updateLabel = ts.Debug.deprecate(ts.factory.updateLabeledStatement, factoryDeprecation); /** @deprecated Use `factory.createThrowStatement` or the factory supplied by your transformation context instead. */ ts.createThrow = ts.Debug.deprecate(ts.factory.createThrowStatement, factoryDeprecation); /** @deprecated Use `factory.updateThrowStatement` or the factory supplied by your transformation context instead. */ ts.updateThrow = ts.Debug.deprecate(ts.factory.updateThrowStatement, factoryDeprecation); /** @deprecated Use `factory.createTryStatement` or the factory supplied by your transformation context instead. */ ts.createTry = ts.Debug.deprecate(ts.factory.createTryStatement, factoryDeprecation); /** @deprecated Use `factory.updateTryStatement` or the factory supplied by your transformation context instead. */ ts.updateTry = ts.Debug.deprecate(ts.factory.updateTryStatement, factoryDeprecation); /** @deprecated Use `factory.createDebuggerStatement` or the factory supplied by your transformation context instead. */ ts.createDebuggerStatement = ts.Debug.deprecate(ts.factory.createDebuggerStatement, factoryDeprecation); /** @deprecated Use `factory.createVariableDeclarationList` or the factory supplied by your transformation context instead. */ ts.createVariableDeclarationList = ts.Debug.deprecate(ts.factory.createVariableDeclarationList, factoryDeprecation); /** @deprecated Use `factory.updateVariableDeclarationList` or the factory supplied by your transformation context instead. */ ts.updateVariableDeclarationList = ts.Debug.deprecate(ts.factory.updateVariableDeclarationList, factoryDeprecation); /** @deprecated Use `factory.createFunctionDeclaration` or the factory supplied by your transformation context instead. */ ts.createFunctionDeclaration = ts.Debug.deprecate(ts.factory.createFunctionDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateFunctionDeclaration` or the factory supplied by your transformation context instead. */ ts.updateFunctionDeclaration = ts.Debug.deprecate(ts.factory.updateFunctionDeclaration, factoryDeprecation); /** @deprecated Use `factory.createClassDeclaration` or the factory supplied by your transformation context instead. */ ts.createClassDeclaration = ts.Debug.deprecate(ts.factory.createClassDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateClassDeclaration` or the factory supplied by your transformation context instead. */ ts.updateClassDeclaration = ts.Debug.deprecate(ts.factory.updateClassDeclaration, factoryDeprecation); /** @deprecated Use `factory.createInterfaceDeclaration` or the factory supplied by your transformation context instead. */ ts.createInterfaceDeclaration = ts.Debug.deprecate(ts.factory.createInterfaceDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateInterfaceDeclaration` or the factory supplied by your transformation context instead. */ ts.updateInterfaceDeclaration = ts.Debug.deprecate(ts.factory.updateInterfaceDeclaration, factoryDeprecation); /** @deprecated Use `factory.createTypeAliasDeclaration` or the factory supplied by your transformation context instead. */ ts.createTypeAliasDeclaration = ts.Debug.deprecate(ts.factory.createTypeAliasDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateTypeAliasDeclaration` or the factory supplied by your transformation context instead. */ ts.updateTypeAliasDeclaration = ts.Debug.deprecate(ts.factory.updateTypeAliasDeclaration, factoryDeprecation); /** @deprecated Use `factory.createEnumDeclaration` or the factory supplied by your transformation context instead. */ ts.createEnumDeclaration = ts.Debug.deprecate(ts.factory.createEnumDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateEnumDeclaration` or the factory supplied by your transformation context instead. */ ts.updateEnumDeclaration = ts.Debug.deprecate(ts.factory.updateEnumDeclaration, factoryDeprecation); /** @deprecated Use `factory.createModuleDeclaration` or the factory supplied by your transformation context instead. */ ts.createModuleDeclaration = ts.Debug.deprecate(ts.factory.createModuleDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateModuleDeclaration` or the factory supplied by your transformation context instead. */ ts.updateModuleDeclaration = ts.Debug.deprecate(ts.factory.updateModuleDeclaration, factoryDeprecation); /** @deprecated Use `factory.createModuleBlock` or the factory supplied by your transformation context instead. */ ts.createModuleBlock = ts.Debug.deprecate(ts.factory.createModuleBlock, factoryDeprecation); /** @deprecated Use `factory.updateModuleBlock` or the factory supplied by your transformation context instead. */ ts.updateModuleBlock = ts.Debug.deprecate(ts.factory.updateModuleBlock, factoryDeprecation); /** @deprecated Use `factory.createCaseBlock` or the factory supplied by your transformation context instead. */ ts.createCaseBlock = ts.Debug.deprecate(ts.factory.createCaseBlock, factoryDeprecation); /** @deprecated Use `factory.updateCaseBlock` or the factory supplied by your transformation context instead. */ ts.updateCaseBlock = ts.Debug.deprecate(ts.factory.updateCaseBlock, factoryDeprecation); /** @deprecated Use `factory.createNamespaceExportDeclaration` or the factory supplied by your transformation context instead. */ ts.createNamespaceExportDeclaration = ts.Debug.deprecate(ts.factory.createNamespaceExportDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateNamespaceExportDeclaration` or the factory supplied by your transformation context instead. */ ts.updateNamespaceExportDeclaration = ts.Debug.deprecate(ts.factory.updateNamespaceExportDeclaration, factoryDeprecation); /** @deprecated Use `factory.createImportEqualsDeclaration` or the factory supplied by your transformation context instead. */ ts.createImportEqualsDeclaration = ts.Debug.deprecate(ts.factory.createImportEqualsDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateImportEqualsDeclaration` or the factory supplied by your transformation context instead. */ ts.updateImportEqualsDeclaration = ts.Debug.deprecate(ts.factory.updateImportEqualsDeclaration, factoryDeprecation); /** @deprecated Use `factory.createImportDeclaration` or the factory supplied by your transformation context instead. */ ts.createImportDeclaration = ts.Debug.deprecate(ts.factory.createImportDeclaration, factoryDeprecation); /** @deprecated Use `factory.updateImportDeclaration` or the factory supplied by your transformation context instead. */ ts.updateImportDeclaration = ts.Debug.deprecate(ts.factory.updateImportDeclaration, factoryDeprecation); /** @deprecated Use `factory.createNamespaceImport` or the factory supplied by your transformation context instead. */ ts.createNamespaceImport = ts.Debug.deprecate(ts.factory.createNamespaceImport, factoryDeprecation); /** @deprecated Use `factory.updateNamespaceImport` or the factory supplied by your transformation context instead. */ ts.updateNamespaceImport = ts.Debug.deprecate(ts.factory.updateNamespaceImport, factoryDeprecation); /** @deprecated Use `factory.createNamedImports` or the factory supplied by your transformation context instead. */ ts.createNamedImports = ts.Debug.deprecate(ts.factory.createNamedImports, factoryDeprecation); /** @deprecated Use `factory.updateNamedImports` or the factory supplied by your transformation context instead. */ ts.updateNamedImports = ts.Debug.deprecate(ts.factory.updateNamedImports, factoryDeprecation); /** @deprecated Use `factory.createImportSpecifier` or the factory supplied by your transformation context instead. */ ts.createImportSpecifier = ts.Debug.deprecate(ts.factory.createImportSpecifier, factoryDeprecation); /** @deprecated Use `factory.updateImportSpecifier` or the factory supplied by your transformation context instead. */ ts.updateImportSpecifier = ts.Debug.deprecate(ts.factory.updateImportSpecifier, factoryDeprecation); /** @deprecated Use `factory.createExportAssignment` or the factory supplied by your transformation context instead. */ ts.createExportAssignment = ts.Debug.deprecate(ts.factory.createExportAssignment, factoryDeprecation); /** @deprecated Use `factory.updateExportAssignment` or the factory supplied by your transformation context instead. */ ts.updateExportAssignment = ts.Debug.deprecate(ts.factory.updateExportAssignment, factoryDeprecation); /** @deprecated Use `factory.createNamedExports` or the factory supplied by your transformation context instead. */ ts.createNamedExports = ts.Debug.deprecate(ts.factory.createNamedExports, factoryDeprecation); /** @deprecated Use `factory.updateNamedExports` or the factory supplied by your transformation context instead. */ ts.updateNamedExports = ts.Debug.deprecate(ts.factory.updateNamedExports, factoryDeprecation); /** @deprecated Use `factory.createExportSpecifier` or the factory supplied by your transformation context instead. */ ts.createExportSpecifier = ts.Debug.deprecate(ts.factory.createExportSpecifier, factoryDeprecation); /** @deprecated Use `factory.updateExportSpecifier` or the factory supplied by your transformation context instead. */ ts.updateExportSpecifier = ts.Debug.deprecate(ts.factory.updateExportSpecifier, factoryDeprecation); /** @deprecated Use `factory.createExternalModuleReference` or the factory supplied by your transformation context instead. */ ts.createExternalModuleReference = ts.Debug.deprecate(ts.factory.createExternalModuleReference, factoryDeprecation); /** @deprecated Use `factory.updateExternalModuleReference` or the factory supplied by your transformation context instead. */ ts.updateExternalModuleReference = ts.Debug.deprecate(ts.factory.updateExternalModuleReference, factoryDeprecation); /** @deprecated Use `factory.createJSDocTypeExpression` or the factory supplied by your transformation context instead. */ ts.createJSDocTypeExpression = ts.Debug.deprecate(ts.factory.createJSDocTypeExpression, factoryDeprecation); /** @deprecated Use `factory.createJSDocTypeTag` or the factory supplied by your transformation context instead. */ ts.createJSDocTypeTag = ts.Debug.deprecate(ts.factory.createJSDocTypeTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocReturnTag` or the factory supplied by your transformation context instead. */ ts.createJSDocReturnTag = ts.Debug.deprecate(ts.factory.createJSDocReturnTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocThisTag` or the factory supplied by your transformation context instead. */ ts.createJSDocThisTag = ts.Debug.deprecate(ts.factory.createJSDocThisTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocComment` or the factory supplied by your transformation context instead. */ ts.createJSDocComment = ts.Debug.deprecate(ts.factory.createJSDocComment, factoryDeprecation); /** @deprecated Use `factory.createJSDocParameterTag` or the factory supplied by your transformation context instead. */ ts.createJSDocParameterTag = ts.Debug.deprecate(ts.factory.createJSDocParameterTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocClassTag` or the factory supplied by your transformation context instead. */ ts.createJSDocClassTag = ts.Debug.deprecate(ts.factory.createJSDocClassTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocAugmentsTag` or the factory supplied by your transformation context instead. */ ts.createJSDocAugmentsTag = ts.Debug.deprecate(ts.factory.createJSDocAugmentsTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocEnumTag` or the factory supplied by your transformation context instead. */ ts.createJSDocEnumTag = ts.Debug.deprecate(ts.factory.createJSDocEnumTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocTemplateTag` or the factory supplied by your transformation context instead. */ ts.createJSDocTemplateTag = ts.Debug.deprecate(ts.factory.createJSDocTemplateTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocTypedefTag` or the factory supplied by your transformation context instead. */ ts.createJSDocTypedefTag = ts.Debug.deprecate(ts.factory.createJSDocTypedefTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocCallbackTag` or the factory supplied by your transformation context instead. */ ts.createJSDocCallbackTag = ts.Debug.deprecate(ts.factory.createJSDocCallbackTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocSignature` or the factory supplied by your transformation context instead. */ ts.createJSDocSignature = ts.Debug.deprecate(ts.factory.createJSDocSignature, factoryDeprecation); /** @deprecated Use `factory.createJSDocPropertyTag` or the factory supplied by your transformation context instead. */ ts.createJSDocPropertyTag = ts.Debug.deprecate(ts.factory.createJSDocPropertyTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocTypeLiteral` or the factory supplied by your transformation context instead. */ ts.createJSDocTypeLiteral = ts.Debug.deprecate(ts.factory.createJSDocTypeLiteral, factoryDeprecation); /** @deprecated Use `factory.createJSDocImplementsTag` or the factory supplied by your transformation context instead. */ ts.createJSDocImplementsTag = ts.Debug.deprecate(ts.factory.createJSDocImplementsTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocAuthorTag` or the factory supplied by your transformation context instead. */ ts.createJSDocAuthorTag = ts.Debug.deprecate(ts.factory.createJSDocAuthorTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocPublicTag` or the factory supplied by your transformation context instead. */ ts.createJSDocPublicTag = ts.Debug.deprecate(ts.factory.createJSDocPublicTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocPrivateTag` or the factory supplied by your transformation context instead. */ ts.createJSDocPrivateTag = ts.Debug.deprecate(ts.factory.createJSDocPrivateTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocProtectedTag` or the factory supplied by your transformation context instead. */ ts.createJSDocProtectedTag = ts.Debug.deprecate(ts.factory.createJSDocProtectedTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocReadonlyTag` or the factory supplied by your transformation context instead. */ ts.createJSDocReadonlyTag = ts.Debug.deprecate(ts.factory.createJSDocReadonlyTag, factoryDeprecation); /** @deprecated Use `factory.createJSDocUnknownTag` or the factory supplied by your transformation context instead. */ ts.createJSDocTag = ts.Debug.deprecate(ts.factory.createJSDocUnknownTag, factoryDeprecation); /** @deprecated Use `factory.createJsxElement` or the factory supplied by your transformation context instead. */ ts.createJsxElement = ts.Debug.deprecate(ts.factory.createJsxElement, factoryDeprecation); /** @deprecated Use `factory.updateJsxElement` or the factory supplied by your transformation context instead. */ ts.updateJsxElement = ts.Debug.deprecate(ts.factory.updateJsxElement, factoryDeprecation); /** @deprecated Use `factory.createJsxSelfClosingElement` or the factory supplied by your transformation context instead. */ ts.createJsxSelfClosingElement = ts.Debug.deprecate(ts.factory.createJsxSelfClosingElement, factoryDeprecation); /** @deprecated Use `factory.updateJsxSelfClosingElement` or the factory supplied by your transformation context instead. */ ts.updateJsxSelfClosingElement = ts.Debug.deprecate(ts.factory.updateJsxSelfClosingElement, factoryDeprecation); /** @deprecated Use `factory.createJsxOpeningElement` or the factory supplied by your transformation context instead. */ ts.createJsxOpeningElement = ts.Debug.deprecate(ts.factory.createJsxOpeningElement, factoryDeprecation); /** @deprecated Use `factory.updateJsxOpeningElement` or the factory supplied by your transformation context instead. */ ts.updateJsxOpeningElement = ts.Debug.deprecate(ts.factory.updateJsxOpeningElement, factoryDeprecation); /** @deprecated Use `factory.createJsxClosingElement` or the factory supplied by your transformation context instead. */ ts.createJsxClosingElement = ts.Debug.deprecate(ts.factory.createJsxClosingElement, factoryDeprecation); /** @deprecated Use `factory.updateJsxClosingElement` or the factory supplied by your transformation context instead. */ ts.updateJsxClosingElement = ts.Debug.deprecate(ts.factory.updateJsxClosingElement, factoryDeprecation); /** @deprecated Use `factory.createJsxFragment` or the factory supplied by your transformation context instead. */ ts.createJsxFragment = ts.Debug.deprecate(ts.factory.createJsxFragment, factoryDeprecation); /** @deprecated Use `factory.createJsxText` or the factory supplied by your transformation context instead. */ ts.createJsxText = ts.Debug.deprecate(ts.factory.createJsxText, factoryDeprecation); /** @deprecated Use `factory.updateJsxText` or the factory supplied by your transformation context instead. */ ts.updateJsxText = ts.Debug.deprecate(ts.factory.updateJsxText, factoryDeprecation); /** @deprecated Use `factory.createJsxOpeningFragment` or the factory supplied by your transformation context instead. */ ts.createJsxOpeningFragment = ts.Debug.deprecate(ts.factory.createJsxOpeningFragment, factoryDeprecation); /** @deprecated Use `factory.createJsxJsxClosingFragment` or the factory supplied by your transformation context instead. */ ts.createJsxJsxClosingFragment = ts.Debug.deprecate(ts.factory.createJsxJsxClosingFragment, factoryDeprecation); /** @deprecated Use `factory.updateJsxFragment` or the factory supplied by your transformation context instead. */ ts.updateJsxFragment = ts.Debug.deprecate(ts.factory.updateJsxFragment, factoryDeprecation); /** @deprecated Use `factory.createJsxAttribute` or the factory supplied by your transformation context instead. */ ts.createJsxAttribute = ts.Debug.deprecate(ts.factory.createJsxAttribute, factoryDeprecation); /** @deprecated Use `factory.updateJsxAttribute` or the factory supplied by your transformation context instead. */ ts.updateJsxAttribute = ts.Debug.deprecate(ts.factory.updateJsxAttribute, factoryDeprecation); /** @deprecated Use `factory.createJsxAttributes` or the factory supplied by your transformation context instead. */ ts.createJsxAttributes = ts.Debug.deprecate(ts.factory.createJsxAttributes, factoryDeprecation); /** @deprecated Use `factory.updateJsxAttributes` or the factory supplied by your transformation context instead. */ ts.updateJsxAttributes = ts.Debug.deprecate(ts.factory.updateJsxAttributes, factoryDeprecation); /** @deprecated Use `factory.createJsxSpreadAttribute` or the factory supplied by your transformation context instead. */ ts.createJsxSpreadAttribute = ts.Debug.deprecate(ts.factory.createJsxSpreadAttribute, factoryDeprecation); /** @deprecated Use `factory.updateJsxSpreadAttribute` or the factory supplied by your transformation context instead. */ ts.updateJsxSpreadAttribute = ts.Debug.deprecate(ts.factory.updateJsxSpreadAttribute, factoryDeprecation); /** @deprecated Use `factory.createJsxExpression` or the factory supplied by your transformation context instead. */ ts.createJsxExpression = ts.Debug.deprecate(ts.factory.createJsxExpression, factoryDeprecation); /** @deprecated Use `factory.updateJsxExpression` or the factory supplied by your transformation context instead. */ ts.updateJsxExpression = ts.Debug.deprecate(ts.factory.updateJsxExpression, factoryDeprecation); /** @deprecated Use `factory.createCaseClause` or the factory supplied by your transformation context instead. */ ts.createCaseClause = ts.Debug.deprecate(ts.factory.createCaseClause, factoryDeprecation); /** @deprecated Use `factory.updateCaseClause` or the factory supplied by your transformation context instead. */ ts.updateCaseClause = ts.Debug.deprecate(ts.factory.updateCaseClause, factoryDeprecation); /** @deprecated Use `factory.createDefaultClause` or the factory supplied by your transformation context instead. */ ts.createDefaultClause = ts.Debug.deprecate(ts.factory.createDefaultClause, factoryDeprecation); /** @deprecated Use `factory.updateDefaultClause` or the factory supplied by your transformation context instead. */ ts.updateDefaultClause = ts.Debug.deprecate(ts.factory.updateDefaultClause, factoryDeprecation); /** @deprecated Use `factory.createHeritageClause` or the factory supplied by your transformation context instead. */ ts.createHeritageClause = ts.Debug.deprecate(ts.factory.createHeritageClause, factoryDeprecation); /** @deprecated Use `factory.updateHeritageClause` or the factory supplied by your transformation context instead. */ ts.updateHeritageClause = ts.Debug.deprecate(ts.factory.updateHeritageClause, factoryDeprecation); /** @deprecated Use `factory.createCatchClause` or the factory supplied by your transformation context instead. */ ts.createCatchClause = ts.Debug.deprecate(ts.factory.createCatchClause, factoryDeprecation); /** @deprecated Use `factory.updateCatchClause` or the factory supplied by your transformation context instead. */ ts.updateCatchClause = ts.Debug.deprecate(ts.factory.updateCatchClause, factoryDeprecation); /** @deprecated Use `factory.createPropertyAssignment` or the factory supplied by your transformation context instead. */ ts.createPropertyAssignment = ts.Debug.deprecate(ts.factory.createPropertyAssignment, factoryDeprecation); /** @deprecated Use `factory.updatePropertyAssignment` or the factory supplied by your transformation context instead. */ ts.updatePropertyAssignment = ts.Debug.deprecate(ts.factory.updatePropertyAssignment, factoryDeprecation); /** @deprecated Use `factory.createShorthandPropertyAssignment` or the factory supplied by your transformation context instead. */ ts.createShorthandPropertyAssignment = ts.Debug.deprecate(ts.factory.createShorthandPropertyAssignment, factoryDeprecation); /** @deprecated Use `factory.updateShorthandPropertyAssignment` or the factory supplied by your transformation context instead. */ ts.updateShorthandPropertyAssignment = ts.Debug.deprecate(ts.factory.updateShorthandPropertyAssignment, factoryDeprecation); /** @deprecated Use `factory.createSpreadAssignment` or the factory supplied by your transformation context instead. */ ts.createSpreadAssignment = ts.Debug.deprecate(ts.factory.createSpreadAssignment, factoryDeprecation); /** @deprecated Use `factory.updateSpreadAssignment` or the factory supplied by your transformation context instead. */ ts.updateSpreadAssignment = ts.Debug.deprecate(ts.factory.updateSpreadAssignment, factoryDeprecation); /** @deprecated Use `factory.createEnumMember` or the factory supplied by your transformation context instead. */ ts.createEnumMember = ts.Debug.deprecate(ts.factory.createEnumMember, factoryDeprecation); /** @deprecated Use `factory.updateEnumMember` or the factory supplied by your transformation context instead. */ ts.updateEnumMember = ts.Debug.deprecate(ts.factory.updateEnumMember, factoryDeprecation); /** @deprecated Use `factory.updateSourceFile` or the factory supplied by your transformation context instead. */ ts.updateSourceFileNode = ts.Debug.deprecate(ts.factory.updateSourceFile, factoryDeprecation); /** @deprecated Use `factory.createNotEmittedStatement` or the factory supplied by your transformation context instead. */ ts.createNotEmittedStatement = ts.Debug.deprecate(ts.factory.createNotEmittedStatement, factoryDeprecation); /** @deprecated Use `factory.createPartiallyEmittedExpression` or the factory supplied by your transformation context instead. */ ts.createPartiallyEmittedExpression = ts.Debug.deprecate(ts.factory.createPartiallyEmittedExpression, factoryDeprecation); /** @deprecated Use `factory.updatePartiallyEmittedExpression` or the factory supplied by your transformation context instead. */ ts.updatePartiallyEmittedExpression = ts.Debug.deprecate(ts.factory.updatePartiallyEmittedExpression, factoryDeprecation); /** @deprecated Use `factory.createCommaListExpression` or the factory supplied by your transformation context instead. */ ts.createCommaList = ts.Debug.deprecate(ts.factory.createCommaListExpression, factoryDeprecation); /** @deprecated Use `factory.updateCommaListExpression` or the factory supplied by your transformation context instead. */ ts.updateCommaList = ts.Debug.deprecate(ts.factory.updateCommaListExpression, factoryDeprecation); /** @deprecated Use `factory.createBundle` or the factory supplied by your transformation context instead. */ ts.createBundle = ts.Debug.deprecate(ts.factory.createBundle, factoryDeprecation); /** @deprecated Use `factory.updateBundle` or the factory supplied by your transformation context instead. */ ts.updateBundle = ts.Debug.deprecate(ts.factory.updateBundle, factoryDeprecation); /** @deprecated Use `factory.createImmediatelyInvokedFunctionExpression` or the factory supplied by your transformation context instead. */ ts.createImmediatelyInvokedFunctionExpression = ts.Debug.deprecate(ts.factory.createImmediatelyInvokedFunctionExpression, factoryDeprecation); /** @deprecated Use `factory.createImmediatelyInvokedArrowFunction` or the factory supplied by your transformation context instead. */ ts.createImmediatelyInvokedArrowFunction = ts.Debug.deprecate(ts.factory.createImmediatelyInvokedArrowFunction, factoryDeprecation); /** @deprecated Use `factory.createVoidZero` or the factory supplied by your transformation context instead. */ ts.createVoidZero = ts.Debug.deprecate(ts.factory.createVoidZero, factoryDeprecation); /** @deprecated Use `factory.createExportDefault` or the factory supplied by your transformation context instead. */ ts.createExportDefault = ts.Debug.deprecate(ts.factory.createExportDefault, factoryDeprecation); /** @deprecated Use `factory.createExternalModuleExport` or the factory supplied by your transformation context instead. */ ts.createExternalModuleExport = ts.Debug.deprecate(ts.factory.createExternalModuleExport, factoryDeprecation); /** @deprecated Use `factory.createNamespaceExport` or the factory supplied by your transformation context instead. */ ts.createNamespaceExport = ts.Debug.deprecate(ts.factory.createNamespaceExport, factoryDeprecation); /** @deprecated Use `factory.updateNamespaceExport` or the factory supplied by your transformation context instead. */ ts.updateNamespaceExport = ts.Debug.deprecate(ts.factory.updateNamespaceExport, factoryDeprecation); /** @deprecated Use `factory.createToken` or the factory supplied by your transformation context instead. */ ts.createToken = ts.Debug.deprecate(function createToken(kind) { return ts.factory.createToken(kind); }, factoryDeprecation); /** @deprecated Use `factory.createIdentifier` or the factory supplied by your transformation context instead. */ ts.createIdentifier = ts.Debug.deprecate(function createIdentifier(text) { return ts.factory.createIdentifier(text, /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined); }, factoryDeprecation); /** @deprecated Use `factory.createTempVariable` or the factory supplied by your transformation context instead. */ ts.createTempVariable = ts.Debug.deprecate(function createTempVariable(recordTempVariable) { return ts.factory.createTempVariable(recordTempVariable, /*reserveInNestedScopes*/ undefined); }, factoryDeprecation); /** @deprecated Use `factory.getGeneratedNameForNode` or the factory supplied by your transformation context instead. */ ts.getGeneratedNameForNode = ts.Debug.deprecate(function getGeneratedNameForNode(node) { return ts.factory.getGeneratedNameForNode(node, /*flags*/ undefined); }, factoryDeprecation); /** @deprecated Use `factory.createUniqueName(text, GeneratedIdentifierFlags.Optimistic)` or the factory supplied by your transformation context instead. */ ts.createOptimisticUniqueName = ts.Debug.deprecate(function createOptimisticUniqueName(text) { return ts.factory.createUniqueName(text, 16 /* GeneratedIdentifierFlags.Optimistic */); }, factoryDeprecation); /** @deprecated Use `factory.createUniqueName(text, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)` or the factory supplied by your transformation context instead. */ ts.createFileLevelUniqueName = ts.Debug.deprecate(function createFileLevelUniqueName(text) { return ts.factory.createUniqueName(text, 16 /* GeneratedIdentifierFlags.Optimistic */ | 32 /* GeneratedIdentifierFlags.FileLevel */); }, factoryDeprecation); /** @deprecated Use `factory.createIndexSignature` or the factory supplied by your transformation context instead. */ ts.createIndexSignature = ts.Debug.deprecate(function createIndexSignature(decorators, modifiers, parameters, type) { return ts.factory.createIndexSignature(decorators, modifiers, parameters, type); }, factoryDeprecation); /** @deprecated Use `factory.createTypePredicateNode` or the factory supplied by your transformation context instead. */ ts.createTypePredicateNode = ts.Debug.deprecate(function createTypePredicateNode(parameterName, type) { return ts.factory.createTypePredicateNode(/*assertsModifier*/ undefined, parameterName, type); }, factoryDeprecation); /** @deprecated Use `factory.updateTypePredicateNode` or the factory supplied by your transformation context instead. */ ts.updateTypePredicateNode = ts.Debug.deprecate(function updateTypePredicateNode(node, parameterName, type) { return ts.factory.updateTypePredicateNode(node, /*assertsModifier*/ undefined, parameterName, type); }, factoryDeprecation); /** @deprecated Use `factory.createStringLiteral`, `factory.createStringLiteralFromNode`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead. */ ts.createLiteral = ts.Debug.deprecate(function createLiteral(value) { if (typeof value === "number") { return ts.factory.createNumericLiteral(value); } // eslint-disable-next-line no-in-operator if (typeof value === "object" && "base10Value" in value) { // PseudoBigInt return ts.factory.createBigIntLiteral(value); } if (typeof value === "boolean") { return value ? ts.factory.createTrue() : ts.factory.createFalse(); } if (typeof value === "string") { return ts.factory.createStringLiteral(value, /*isSingleQuote*/ undefined); } return ts.factory.createStringLiteralFromNode(value); }, { since: "4.0", warnAfter: "4.1", message: "Use `factory.createStringLiteral`, `factory.createStringLiteralFromNode`, `factory.createNumericLiteral`, `factory.createBigIntLiteral`, `factory.createTrue`, `factory.createFalse`, or the factory supplied by your transformation context instead." }); /** @deprecated Use `factory.createMethodSignature` or the factory supplied by your transformation context instead. */ ts.createMethodSignature = ts.Debug.deprecate(function createMethodSignature(typeParameters, parameters, type, name, questionToken) { return ts.factory.createMethodSignature(/*modifiers*/ undefined, name, questionToken, typeParameters, parameters, type); }, factoryDeprecation); /** @deprecated Use `factory.updateMethodSignature` or the factory supplied by your transformation context instead. */ ts.updateMethodSignature = ts.Debug.deprecate(function updateMethodSignature(node, typeParameters, parameters, type, name, questionToken) { return ts.factory.updateMethodSignature(node, node.modifiers, name, questionToken, typeParameters, parameters, type); }, factoryDeprecation); /** @deprecated Use `factory.createTypeOperatorNode` or the factory supplied by your transformation context instead. */ ts.createTypeOperatorNode = ts.Debug.deprecate(function createTypeOperatorNode(operatorOrType, type) { var operator; if (type) { operator = operatorOrType; } else { type = operatorOrType; operator = 140 /* SyntaxKind.KeyOfKeyword */; } return ts.factory.createTypeOperatorNode(operator, type); }, factoryDeprecation); /** @deprecated Use `factory.createTaggedTemplate` or the factory supplied by your transformation context instead. */ ts.createTaggedTemplate = ts.Debug.deprecate(function createTaggedTemplate(tag, typeArgumentsOrTemplate, template) { var typeArguments; if (template) { typeArguments = typeArgumentsOrTemplate; } else { template = typeArgumentsOrTemplate; } return ts.factory.createTaggedTemplateExpression(tag, typeArguments, template); }, factoryDeprecation); /** @deprecated Use `factory.updateTaggedTemplate` or the factory supplied by your transformation context instead. */ ts.updateTaggedTemplate = ts.Debug.deprecate(function updateTaggedTemplate(node, tag, typeArgumentsOrTemplate, template) { var typeArguments; if (template) { typeArguments = typeArgumentsOrTemplate; } else { template = typeArgumentsOrTemplate; } return ts.factory.updateTaggedTemplateExpression(node, tag, typeArguments, template); }, factoryDeprecation); /** @deprecated Use `factory.updateBinary` or the factory supplied by your transformation context instead. */ ts.updateBinary = ts.Debug.deprecate(function updateBinary(node, left, right, operator) { if (operator === void 0) { operator = node.operatorToken; } if (typeof operator === "number") { operator = operator === node.operatorToken.kind ? node.operatorToken : ts.factory.createToken(operator); } return ts.factory.updateBinaryExpression(node, left, operator, right); }, factoryDeprecation); /** @deprecated Use `factory.createConditional` or the factory supplied by your transformation context instead. */ ts.createConditional = ts.Debug.deprecate(function createConditional(condition, questionTokenOrWhenTrue, whenTrueOrWhenFalse, colonToken, whenFalse) { return arguments.length === 5 ? ts.factory.createConditionalExpression(condition, questionTokenOrWhenTrue, whenTrueOrWhenFalse, colonToken, whenFalse) : arguments.length === 3 ? ts.factory.createConditionalExpression(condition, ts.factory.createToken(57 /* SyntaxKind.QuestionToken */), questionTokenOrWhenTrue, ts.factory.createToken(58 /* SyntaxKind.ColonToken */), whenTrueOrWhenFalse) : ts.Debug.fail("Argument count mismatch"); }, factoryDeprecation); /** @deprecated Use `factory.createYield` or the factory supplied by your transformation context instead. */ ts.createYield = ts.Debug.deprecate(function createYield(asteriskTokenOrExpression, expression) { var asteriskToken; if (expression) { asteriskToken = asteriskTokenOrExpression; } else { expression = asteriskTokenOrExpression; } return ts.factory.createYieldExpression(asteriskToken, expression); }, factoryDeprecation); /** @deprecated Use `factory.createClassExpression` or the factory supplied by your transformation context instead. */ ts.createClassExpression = ts.Debug.deprecate(function createClassExpression(modifiers, name, typeParameters, heritageClauses, members) { return ts.factory.createClassExpression(/*decorators*/ undefined, modifiers, name, typeParameters, heritageClauses, members); }, factoryDeprecation); /** @deprecated Use `factory.updateClassExpression` or the factory supplied by your transformation context instead. */ ts.updateClassExpression = ts.Debug.deprecate(function updateClassExpression(node, modifiers, name, typeParameters, heritageClauses, members) { return ts.factory.updateClassExpression(node, /*decorators*/ undefined, modifiers, name, typeParameters, heritageClauses, members); }, factoryDeprecation); /** @deprecated Use `factory.createPropertySignature` or the factory supplied by your transformation context instead. */ ts.createPropertySignature = ts.Debug.deprecate(function createPropertySignature(modifiers, name, questionToken, type, initializer) { var node = ts.factory.createPropertySignature(modifiers, name, questionToken, type); node.initializer = initializer; return node; }, factoryDeprecation); /** @deprecated Use `factory.updatePropertySignature` or the factory supplied by your transformation context instead. */ ts.updatePropertySignature = ts.Debug.deprecate(function updatePropertySignature(node, modifiers, name, questionToken, type, initializer) { var updated = ts.factory.updatePropertySignature(node, modifiers, name, questionToken, type); if (node.initializer !== initializer) { if (updated === node) { updated = ts.factory.cloneNode(node); } updated.initializer = initializer; } return updated; }, factoryDeprecation); /** @deprecated Use `factory.createExpressionWithTypeArguments` or the factory supplied by your transformation context instead. */ ts.createExpressionWithTypeArguments = ts.Debug.deprecate(function createExpressionWithTypeArguments(typeArguments, expression) { return ts.factory.createExpressionWithTypeArguments(expression, typeArguments); }, factoryDeprecation); /** @deprecated Use `factory.updateExpressionWithTypeArguments` or the factory supplied by your transformation context instead. */ ts.updateExpressionWithTypeArguments = ts.Debug.deprecate(function updateExpressionWithTypeArguments(node, typeArguments, expression) { return ts.factory.updateExpressionWithTypeArguments(node, expression, typeArguments); }, factoryDeprecation); /** @deprecated Use `factory.createArrowFunction` or the factory supplied by your transformation context instead. */ ts.createArrowFunction = ts.Debug.deprecate(function createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanTokenOrBody, body) { return arguments.length === 6 ? ts.factory.createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanTokenOrBody, body) : arguments.length === 5 ? ts.factory.createArrowFunction(modifiers, typeParameters, parameters, type, /*equalsGreaterThanToken*/ undefined, equalsGreaterThanTokenOrBody) : ts.Debug.fail("Argument count mismatch"); }, factoryDeprecation); /** @deprecated Use `factory.updateArrowFunction` or the factory supplied by your transformation context instead. */ ts.updateArrowFunction = ts.Debug.deprecate(function updateArrowFunction(node, modifiers, typeParameters, parameters, type, equalsGreaterThanTokenOrBody, body) { return arguments.length === 7 ? ts.factory.updateArrowFunction(node, modifiers, typeParameters, parameters, type, equalsGreaterThanTokenOrBody, body) : arguments.length === 6 ? ts.factory.updateArrowFunction(node, modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, equalsGreaterThanTokenOrBody) : ts.Debug.fail("Argument count mismatch"); }, factoryDeprecation); /** @deprecated Use `factory.createVariableDeclaration` or the factory supplied by your transformation context instead. */ ts.createVariableDeclaration = ts.Debug.deprecate(function createVariableDeclaration(name, exclamationTokenOrType, typeOrInitializer, initializer) { return arguments.length === 4 ? ts.factory.createVariableDeclaration(name, exclamationTokenOrType, typeOrInitializer, initializer) : arguments.length >= 1 && arguments.length <= 3 ? ts.factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, exclamationTokenOrType, typeOrInitializer) : ts.Debug.fail("Argument count mismatch"); }, factoryDeprecation); /** @deprecated Use `factory.updateVariableDeclaration` or the factory supplied by your transformation context instead. */ ts.updateVariableDeclaration = ts.Debug.deprecate(function updateVariableDeclaration(node, name, exclamationTokenOrType, typeOrInitializer, initializer) { return arguments.length === 5 ? ts.factory.updateVariableDeclaration(node, name, exclamationTokenOrType, typeOrInitializer, initializer) : arguments.length === 4 ? ts.factory.updateVariableDeclaration(node, name, node.exclamationToken, exclamationTokenOrType, typeOrInitializer) : ts.Debug.fail("Argument count mismatch"); }, factoryDeprecation); /** @deprecated Use `factory.createImportClause` or the factory supplied by your transformation context instead. */ ts.createImportClause = ts.Debug.deprecate(function createImportClause(name, namedBindings, isTypeOnly) { if (isTypeOnly === void 0) { isTypeOnly = false; } return ts.factory.createImportClause(isTypeOnly, name, namedBindings); }, factoryDeprecation); /** @deprecated Use `factory.updateImportClause` or the factory supplied by your transformation context instead. */ ts.updateImportClause = ts.Debug.deprecate(function updateImportClause(node, name, namedBindings, isTypeOnly) { return ts.factory.updateImportClause(node, isTypeOnly, name, namedBindings); }, factoryDeprecation); /** @deprecated Use `factory.createExportDeclaration` or the factory supplied by your transformation context instead. */ ts.createExportDeclaration = ts.Debug.deprecate(function createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier, isTypeOnly) { if (isTypeOnly === void 0) { isTypeOnly = false; } return ts.factory.createExportDeclaration(decorators, modifiers, isTypeOnly, exportClause, moduleSpecifier); }, factoryDeprecation); /** @deprecated Use `factory.updateExportDeclaration` or the factory supplied by your transformation context instead. */ ts.updateExportDeclaration = ts.Debug.deprecate(function updateExportDeclaration(node, decorators, modifiers, exportClause, moduleSpecifier, isTypeOnly) { return ts.factory.updateExportDeclaration(node, decorators, modifiers, isTypeOnly, exportClause, moduleSpecifier, node.assertClause); }, factoryDeprecation); /** @deprecated Use `factory.createJSDocParameterTag` or the factory supplied by your transformation context instead. */ ts.createJSDocParamTag = ts.Debug.deprecate(function createJSDocParamTag(name, isBracketed, typeExpression, comment) { return ts.factory.createJSDocParameterTag(/*tagName*/ undefined, name, isBracketed, typeExpression, /*isNameFirst*/ false, comment ? ts.factory.createNodeArray([ts.factory.createJSDocText(comment)]) : undefined); }, factoryDeprecation); /** @deprecated Use `factory.createComma` or the factory supplied by your transformation context instead. */ ts.createComma = ts.Debug.deprecate(function createComma(left, right) { return ts.factory.createComma(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createLessThan` or the factory supplied by your transformation context instead. */ ts.createLessThan = ts.Debug.deprecate(function createLessThan(left, right) { return ts.factory.createLessThan(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createAssignment` or the factory supplied by your transformation context instead. */ ts.createAssignment = ts.Debug.deprecate(function createAssignment(left, right) { return ts.factory.createAssignment(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createStrictEquality` or the factory supplied by your transformation context instead. */ ts.createStrictEquality = ts.Debug.deprecate(function createStrictEquality(left, right) { return ts.factory.createStrictEquality(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createStrictInequality` or the factory supplied by your transformation context instead. */ ts.createStrictInequality = ts.Debug.deprecate(function createStrictInequality(left, right) { return ts.factory.createStrictInequality(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createAdd` or the factory supplied by your transformation context instead. */ ts.createAdd = ts.Debug.deprecate(function createAdd(left, right) { return ts.factory.createAdd(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createSubtract` or the factory supplied by your transformation context instead. */ ts.createSubtract = ts.Debug.deprecate(function createSubtract(left, right) { return ts.factory.createSubtract(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createLogicalAnd` or the factory supplied by your transformation context instead. */ ts.createLogicalAnd = ts.Debug.deprecate(function createLogicalAnd(left, right) { return ts.factory.createLogicalAnd(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createLogicalOr` or the factory supplied by your transformation context instead. */ ts.createLogicalOr = ts.Debug.deprecate(function createLogicalOr(left, right) { return ts.factory.createLogicalOr(left, right); }, factoryDeprecation); /** @deprecated Use `factory.createPostfixIncrement` or the factory supplied by your transformation context instead. */ ts.createPostfixIncrement = ts.Debug.deprecate(function createPostfixIncrement(operand) { return ts.factory.createPostfixIncrement(operand); }, factoryDeprecation); /** @deprecated Use `factory.createLogicalNot` or the factory supplied by your transformation context instead. */ ts.createLogicalNot = ts.Debug.deprecate(function createLogicalNot(operand) { return ts.factory.createLogicalNot(operand); }, factoryDeprecation); /** @deprecated Use an appropriate `factory` method instead. */ ts.createNode = ts.Debug.deprecate(function createNode(kind, pos, end) { if (pos === void 0) { pos = 0; } if (end === void 0) { end = 0; } return ts.setTextRangePosEnd(kind === 305 /* SyntaxKind.SourceFile */ ? ts.parseBaseNodeFactory.createBaseSourceFileNode(kind) : kind === 79 /* SyntaxKind.Identifier */ ? ts.parseBaseNodeFactory.createBaseIdentifierNode(kind) : kind === 80 /* SyntaxKind.PrivateIdentifier */ ? ts.parseBaseNodeFactory.createBasePrivateIdentifierNode(kind) : !ts.isNodeKind(kind) ? ts.parseBaseNodeFactory.createBaseTokenNode(kind) : ts.parseBaseNodeFactory.createBaseNode(kind), pos, end); }, { since: "4.0", warnAfter: "4.1", message: "Use an appropriate `factory` method instead." }); /** * Creates a shallow, memberwise clone of a node ~for mutation~ with its `pos`, `end`, and `parent` set. * * NOTE: It is unsafe to change any properties of a `Node` that relate to its AST children, as those changes won't be * captured with respect to transformations. * * @deprecated Use an appropriate `factory.update...` method instead, use `setCommentRange` or `setSourceMapRange`, and avoid setting `parent`. */ ts.getMutableClone = ts.Debug.deprecate(function getMutableClone(node) { var clone = ts.factory.cloneNode(node); ts.setTextRange(clone, node); ts.setParent(clone, node.parent); return clone; }, { since: "4.0", warnAfter: "4.1", message: "Use an appropriate `factory.update...` method instead, use `setCommentRange` or `setSourceMapRange`, and avoid setting `parent`." }); // #endregion Node Factory top-level exports // DEPRECATION: Renamed node tests // DEPRECATION PLAN: // - soft: 4.0 // - warn: 4.1 // - error: TBD // #region Renamed node Tests /** @deprecated Use `isTypeAssertionExpression` instead. */ ts.isTypeAssertion = ts.Debug.deprecate(function isTypeAssertion(node) { return node.kind === 211 /* SyntaxKind.TypeAssertionExpression */; }, { since: "4.0", warnAfter: "4.1", message: "Use `isTypeAssertionExpression` instead." }); // #endregion // DEPRECATION: Renamed node tests // DEPRECATION PLAN: // - soft: 4.2 // - warn: 4.3 // - error: TBD // #region Renamed node Tests /** * @deprecated Use `isMemberName` instead. */ ts.isIdentifierOrPrivateIdentifier = ts.Debug.deprecate(function isIdentifierOrPrivateIdentifier(node) { return ts.isMemberName(node); }, { since: "4.2", warnAfter: "4.3", message: "Use `isMemberName` instead." }); // #endregion Renamed node Tests })(ts || (ts = {})); //# sourceMappingURL=typescript.js.map