ken === 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<T>(onfulfilled: (value: T) => void) { //....}
            //      interface Test {
            //          pr/*destination*/op1: number
            //      }
            //      bar<Test>(({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<string> | Array<number>; a.length
            // The property length will have two declarations of property length coming
            // from Array<T> - Array<string> and Array<number>
            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 <unknown>.
                    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)))), "\"")
                        : "<global>";
                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 "<unknown>";
            }
        }
        /** 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 "<expr> = 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 "<class>";
            }
            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 "<function>";
        }
        // 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 + ">...</" + 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<T, U>#(a, b)#   -> The token is either not associated with a list, or ends a list, so the session should end
                //    Case 3:
                //          foo<T#, U#>(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 { ... }
                //      <MainButton /*signatureHelp*/
                var attributeSpanStart = parent.attributes.pos;
                var attributeSpanEnd = ts.skipTrivia(sourceFile.text, parent.attributes.end, /*stopAfterLineBreak*/ false);
                return {
                    isTypeParameterList: false,
                    invocation: { kind: 0 /* InvocationKind.Call */, node: parent },
                    argumentsSpan: ts.createTextSpan(attributeSpanStart, attributeSpanEnd - attributeSpanStart),
                    argumentIndex: 0,
                    argumentCount: 1
                };
            }
            else {
                var typeArgInfo = ts.getPossibleTypeArgumentsInfo(node, sourceFile);
                if (typeArgInfo) {
                    var called = typeArgInfo.called, nTypeArguments = typeArgInfo.nTypeArguments;
                    var invocation = { kind: 1 /* InvocationKind.TypeArgs */, called: called };
                    var argumentsSpan = ts.createTextSpanFromBounds(called.getStart(sourceFile), node.end);
                    return { isTypeParameterList: true, invocation: invocation, argumentsSpan: argumentsSpan, argumentIndex: nTypeArguments, argumentCount: nTypeArguments + 1 };
                }
                return undefined;
            }
        }
        function getImmediatelyContainingArgumentOrContextualParameterInfo(node, position, sourceFile, checker) {
            return tryGetParameterInfo(node, position, sourceFile, checker) || getImmediatelyContainingArgumentInfo(node, position, sourceFile);
        }
        function getHighestBinary(b) {
            return ts.isBinaryExpression(b.parent) ? getHighestBinary(b.parent) : b;
        }
        function countBinaryExpressionParameters(b) {
            return ts.isBinaryExpression(b.left) ? countBinaryExpressionParameters(b.left) + 1 : 2;
        }
        function tryGetParameterInfo(startingToken, position, sourceFile, checker) {
            var info = getContextualSignatureLocationInfo(startingToken, sourceFile, position, checker);
            if (!info)
                return undefined;
            var contextualType = info.contextualType, argumentIndex = info.argumentIndex, argumentCount = info.argumentCount, argumentsSpan = info.argumentsSpan;
            // for optional function condition.
            var nonNullableContextualType = contextualType.getNonNullableType();
            var symbol = nonNullableContextualType.symbol;
            if (symbol === undefined)
                return undefined;
            var signature = ts.lastOrUndefined(nonNullableContextualType.getCallSignatures());
            if (signature === undefined)
                return undefined;
            var invocation = { kind: 2 /* InvocationKind.Contextual */, signature: signature, node: startingToken, symbol: chooseBetterSymbol(symbol) };
            return { isTypeParameterList: false, invocation: invocation, argumentsSpan: argumentsSpan, argumentIndex: argumentIndex, argumentCount: argumentCount };
        }
        function getContextualSignatureLocationInfo(startingToken, sourceFile, position, checker) {
            if (startingToken.kind !== 20 /* SyntaxKind.OpenParenToken */ && startingToken.kind !== 27 /* SyntaxKind.CommaToken */)
                return undefined;
            var parent = startingToken.parent;
            switch (parent.kind) {
                case 212 /* SyntaxKind.ParenthesizedExpression */:
                case 169 /* SyntaxKind.MethodDeclaration */:
                case 213 /* SyntaxKind.FunctionExpression */:
                case 214 /* SyntaxKind.ArrowFunction */:
                    var info = getArgumentOrParameterListInfo(startingToken, position, sourceFile);
                    if (!info)
                        return undefined;
                    var argumentIndex = info.argumentIndex, argumentCount = info.argumentCount, argumentsSpan = info.argumentsSpan;
                    var contextualType = ts.isMethodDeclaration(parent) ? checker.getContextualTypeForObjectLiteralElement(parent) : checker.getContextualType(parent);
                    return contextualType && { contextualType: contextualType, argumentIndex: argumentIndex, argumentCount: argumentCount, argumentsSpan: argumentsSpan };
                case 221 /* SyntaxKind.BinaryExpression */: {
                    var highestBinary = getHighestBinary(parent);
                    var contextualType_1 = checker.getContextualType(highestBinary);
                    var argumentIndex_1 = startingToken.kind === 20 /* SyntaxKind.OpenParenToken */ ? 0 : countBinaryExpressionParameters(parent) - 1;
                    var argumentCount_1 = countBinaryExpressionParameters(highestBinary);
                    return contextualType_1 && { contextualType: contextualType_1, argumentIndex: argumentIndex_1, argumentCount: argumentCount_1, argumentsSpan: ts.createTextSpanFromNode(parent) };
                }
                default:
                    return undefined;
            }
        }
        // The type of a function type node has a symbol at that node, but it's better to use the symbol for a parameter or type alias.
        function chooseBetterSymbol(s) {
            return s.name === "__type" /* InternalSymbolName.Type */
                ? ts.firstDefined(s.declarations, function (d) { return ts.isFunctionTypeNode(d) ? d.parent.symbol : undefined; }) || s
                : s;
        }
        function getArgumentIndex(argumentsList, node) {
            // The list we got back can include commas.  In the presence of errors it may
            // also just have nodes without commas.  For example "Foo(a b c)" will have 3
            // args without commas. We want to find what index we're at.  So we count
            // forward until we hit ourselves, only incrementing the index if it isn't a
            // comma.
            //
            // Note: the subtlety around trailing commas (in getArgumentCount) does not apply
            // here.  That's because we're only walking forward until we hit the node we're
            // on.  In that case, even if we're after the trailing comma, we'll still see
            // that trailing comma in the list, and we'll have generated the appropriate
            // arg index.
            var argumentIndex = 0;
            for (var _i = 0, _a = argumentsList.getChildren(); _i < _a.length; _i++) {
                var child = _a[_i];
                if (child === node) {
                    break;
                }
                if (child.kind !== 27 /* SyntaxKind.CommaToken */) {
                    argumentIndex++;
                }
            }
            return argumentIndex;
        }
        function getArgumentCount(argumentsList, ignoreTrailingComma) {
            // The argument count for a list is normally the number of non-comma children it has.
            // For example, if you have "Foo(a,b)" then there will be three children of the arg
            // list 'a' '<comma>' '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' '<comma>'.  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' '<comma>' '<missing>'
            // 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 <className>
                    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> = 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<ClassDeclaration> implemented as Map<node id, ClassDeclaration>
                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<separator>#
                        // ###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<number> {      | async function f9(): Promise<number> {
                                //     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 <<name>> = 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 = {
            ">": "&gt;",
            "}": "&rbrace;",
        };
        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<import("./b").OtherType<...>>',
         * 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 "<a /><a />"
            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((<decl>) => {})`
            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<void>} */(");
                    }
                }
                else {
                    if (!parameterType || parameterType.flags & 2 /* TypeFlags.Unknown */) {
                        // add `void` type argument
                        changes.insertText(sourceFile, decl.parent.parent.expression.end, "<void>");
                    }
                }
            }
        }
        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<symbolId, subst> to map<nodeId, subst> 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<T extends { a?: /**/T }>(): 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<T>{} )
            // 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: "</".concat(element.openingElement.tagName.getText(sourceFile), ">") };
            }
            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) {
    var server;
    (function (server) {
        /* @internal */
        server.ActionSet = "action::set";
        /* @internal */
        server.ActionInvalidate = "action::invalidate";
        /* @internal */
        server.ActionPackageInstalled = "action::packageInstalled";
        /* @internal */
        server.EventTypesRegistry = "event::typesRegistry";
        /* @internal */
        server.EventBeginInstallTypes = "event::beginInstallTypes";
        /* @internal */
        server.EventEndInstallTypes = "event::endInstallTypes";
        /* @internal */
        server.EventInitializationFailed = "event::initializationFailed";
        /* @internal */
        var Arguments;
        (function (Arguments) {
            Arguments.GlobalCacheLocation = "--globalTypingsCacheLocation";
            Arguments.LogFile = "--logFile";
            Arguments.EnableTelemetry = "--enableTelemetry";
            Arguments.TypingSafeListLocation = "--typingSafeListLocation";
            Arguments.TypesMapLocation = "--typesMapLocation";
            /**
             * This argument specifies the location of the NPM executable.
             * typingsInstaller will run the command with `${npmLocation} install ...`.
             */
            Arguments.NpmLocation = "--npmLocation";
            /**
             * Flag indicating that the typings installer should try to validate the default npm location.
             * If the default npm is not found when this flag is enabled, fallback to `npm install`
             */
            Arguments.ValidateDefaultNpmLocation = "--validateDefaultNpmLocation";
        })(Arguments = server.Arguments || (server.Arguments = {}));
        /* @internal */
        function hasArgument(argumentName) {
            return ts.sys.args.indexOf(argumentName) >= 0;
        }
        server.hasArgument = hasArgument;
        /* @internal */
        function findArgument(argumentName) {
            var index = ts.sys.args.indexOf(argumentName);
            return index >= 0 && index < ts.sys.args.length - 1
                ? ts.sys.args[index + 1]
                : undefined;
        }
        server.findArgument = findArgument;
        /* @internal */
        function nowString() {
            // E.g. "12:34:56.789"
            var d = new Date();
            return "".concat(ts.padLeft(d.getHours().toString(), 2, "0"), ":").concat(ts.padLeft(d.getMinutes().toString(), 2, "0"), ":").concat(ts.padLeft(d.getSeconds().toString(), 2, "0"), ".").concat(ts.padLeft(d.getMilliseconds().toString(), 3, "0"));
        }
        server.nowString = nowString;
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/* @internal */
var ts;
(function (ts) {
    var JsTyping;
    (function (JsTyping) {
        function isTypingUpToDate(cachedTyping, availableTypingVersions) {
            var availableVersion = new ts.Version(ts.getProperty(availableTypingVersions, "ts".concat(ts.versionMajorMinor)) || ts.getProperty(availableTypingVersions, "latest"));
            return availableVersion.compareTo(cachedTyping.version) <= 0;
        }
        JsTyping.isTypingUpToDate = isTypingUpToDate;
        var unprefixedNodeCoreModuleList = [
            "assert",
            "assert/strict",
            "async_hooks",
            "buffer",
            "child_process",
            "cluster",
            "console",
            "constants",
            "crypto",
            "dgram",
            "diagnostics_channel",
            "dns",
            "dns/promises",
            "domain",
            "events",
            "fs",
            "fs/promises",
            "http",
            "https",
            "http2",
            "inspector",
            "module",
            "net",
            "os",
            "path",
            "perf_hooks",
            "process",
            "punycode",
            "querystring",
            "readline",
            "repl",
            "stream",
            "stream/promises",
            "string_decoder",
            "timers",
            "timers/promises",
            "tls",
            "trace_events",
            "tty",
            "url",
            "util",
            "util/types",
            "v8",
            "vm",
            "wasi",
            "worker_threads",
            "zlib"
        ];
        JsTyping.prefixedNodeCoreModuleList = unprefixedNodeCoreModuleList.map(function (name) { return "node:".concat(name); });
        JsTyping.nodeCoreModuleList = __spreadArray(__spreadArray([], unprefixedNodeCoreModuleList, true), JsTyping.prefixedNodeCoreModuleList, true);
        JsTyping.nodeCoreModules = new ts.Set(JsTyping.nodeCoreModuleList);
        function nonRelativeModuleNameForTypingCache(moduleName) {
            return JsTyping.nodeCoreModules.has(moduleName) ? "node" : moduleName;
        }
        JsTyping.nonRelativeModuleNameForTypingCache = nonRelativeModuleNameForTypingCache;
        function loadSafeList(host, safeListPath) {
            var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); });
            return new ts.Map(ts.getEntries(result.config));
        }
        JsTyping.loadSafeList = loadSafeList;
        function loadTypesMap(host, typesMapPath) {
            var result = ts.readConfigFile(typesMapPath, function (path) { return host.readFile(path); });
            if (result.config) {
                return new ts.Map(ts.getEntries(result.config.simpleMap));
            }
            return undefined;
        }
        JsTyping.loadTypesMap = loadTypesMap;
        /**
         * @param host is the object providing I/O related operations.
         * @param fileNames are the file names that belong to the same project
         * @param projectRootPath is the path to the project root directory
         * @param safeListPath is the path used to retrieve the safe list
         * @param packageNameToTypingLocation is the map of package names to their cached typing locations and installed versions
         * @param typeAcquisition is used to customize the typing acquisition process
         * @param compilerOptions are used as a source for typing inference
         */
        function discoverTypings(host, log, fileNames, projectRootPath, safeList, packageNameToTypingLocation, typeAcquisition, unresolvedImports, typesRegistry) {
            if (!typeAcquisition || !typeAcquisition.enable) {
                return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] };
            }
            // A typing name to typing file path mapping
            var inferredTypings = new ts.Map();
            // Only infer typings for .js and .jsx files
            fileNames = ts.mapDefined(fileNames, function (fileName) {
                var path = ts.normalizePath(fileName);
                if (ts.hasJSFileExtension(path)) {
                    return path;
                }
            });
            var filesToWatch = [];
            if (typeAcquisition.include)
                addInferredTypings(typeAcquisition.include, "Explicitly included types");
            var exclude = typeAcquisition.exclude || [];
            // Directories to search for package.json, bower.json and other typing information
            var possibleSearchDirs = new ts.Set(fileNames.map(ts.getDirectoryPath));
            possibleSearchDirs.add(projectRootPath);
            possibleSearchDirs.forEach(function (searchDir) {
                getTypingNames(searchDir, "bower.json", "bower_components", filesToWatch);
                getTypingNames(searchDir, "package.json", "node_modules", filesToWatch);
            });
            if (!typeAcquisition.disableFilenameBasedTypeAcquisition) {
                getTypingNamesFromSourceFileNames(fileNames);
            }
            // add typings for unresolved imports
            if (unresolvedImports) {
                var module_1 = ts.deduplicate(unresolvedImports.map(nonRelativeModuleNameForTypingCache), ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive);
                addInferredTypings(module_1, "Inferred typings from unresolved imports");
            }
            // Add the cached typing locations for inferred typings that are already installed
            packageNameToTypingLocation.forEach(function (typing, name) {
                var registryEntry = typesRegistry.get(name);
                if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && registryEntry !== undefined && isTypingUpToDate(typing, registryEntry)) {
                    inferredTypings.set(name, typing.typingLocation);
                }
            });
            // Remove typings that the user has added to the exclude list
            for (var _i = 0, exclude_1 = exclude; _i < exclude_1.length; _i++) {
                var excludeTypingName = exclude_1[_i];
                var didDelete = inferredTypings.delete(excludeTypingName);
                if (didDelete && log)
                    log("Typing for ".concat(excludeTypingName, " is in exclude list, will be ignored."));
            }
            var newTypingNames = [];
            var cachedTypingPaths = [];
            inferredTypings.forEach(function (inferred, typing) {
                if (inferred !== undefined) {
                    cachedTypingPaths.push(inferred);
                }
                else {
                    newTypingNames.push(typing);
                }
            });
            var result = { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch };
            if (log)
                log("Result: ".concat(JSON.stringify(result)));
            return result;
            function addInferredTyping(typingName) {
                if (!inferredTypings.has(typingName)) {
                    inferredTypings.set(typingName, undefined); // TODO: GH#18217
                }
            }
            function addInferredTypings(typingNames, message) {
                if (log)
                    log("".concat(message, ": ").concat(JSON.stringify(typingNames)));
                ts.forEach(typingNames, addInferredTyping);
            }
            /**
             * Adds inferred typings from manifest/module pairs (think package.json + node_modules)
             *
             * @param projectRootPath is the path to the directory where to look for package.json, bower.json and other typing information
             * @param manifestName is the name of the manifest (package.json or bower.json)
             * @param modulesDirName is the directory name for modules (node_modules or bower_components). Should be lowercase!
             * @param filesToWatch are the files to watch for changes. We will push things into this array.
             */
            function getTypingNames(projectRootPath, manifestName, modulesDirName, filesToWatch) {
                // First, we check the manifests themselves. They're not
                // _required_, but they allow us to do some filtering when dealing
                // with big flat dep directories.
                var manifestPath = ts.combinePaths(projectRootPath, manifestName);
                var manifest;
                var manifestTypingNames;
                if (host.fileExists(manifestPath)) {
                    filesToWatch.push(manifestPath);
                    manifest = ts.readConfigFile(manifestPath, function (path) { return host.readFile(path); }).config;
                    manifestTypingNames = ts.flatMap([manifest.dependencies, manifest.devDependencies, manifest.optionalDependencies, manifest.peerDependencies], ts.getOwnKeys);
                    addInferredTypings(manifestTypingNames, "Typing names in '".concat(manifestPath, "' dependencies"));
                }
                // Now we scan the directories for typing information in
                // already-installed dependencies (if present). Note that this
                // step happens regardless of whether a manifest was present,
                // which is certainly a valid configuration, if an unusual one.
                var packagesFolderPath = ts.combinePaths(projectRootPath, modulesDirName);
                filesToWatch.push(packagesFolderPath);
                if (!host.directoryExists(packagesFolderPath)) {
                    return;
                }
                // There's two cases we have to take into account here:
                // 1. If manifest is undefined, then we're not using a manifest.
                //    That means that we should scan _all_ dependencies at the top
                //    level of the modulesDir.
                // 2. If manifest is defined, then we can do some special
                //    filtering to reduce the amount of scanning we need to do.
                //
                // Previous versions of this algorithm checked for a `_requiredBy`
                // field in the package.json, but that field is only present in
                // `npm@>=3 <7`.
                // Package names that do **not** provide their own typings, so
                // we'll look them up.
                var packageNames = [];
                var dependencyManifestNames = manifestTypingNames
                    // This is #1 described above.
                    ? manifestTypingNames.map(function (typingName) { return ts.combinePaths(packagesFolderPath, typingName, manifestName); })
                    // And #2. Depth = 3 because scoped packages look like `node_modules/@foo/bar/package.json`
                    : host.readDirectory(packagesFolderPath, [".json" /* Extension.Json */], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 3)
                        .filter(function (manifestPath) {
                        if (ts.getBaseFileName(manifestPath) !== manifestName) {
                            return false;
                        }
                        // It's ok to treat
                        // `node_modules/@foo/bar/package.json` as a manifest,
                        // but not `node_modules/jquery/nested/package.json`.
                        // We only assume depth 3 is ok for formally scoped
                        // packages. So that needs this dance here.
                        var pathComponents = ts.getPathComponents(ts.normalizePath(manifestPath));
                        var isScoped = pathComponents[pathComponents.length - 3][0] === "@";
                        return isScoped && pathComponents[pathComponents.length - 4].toLowerCase() === modulesDirName || // `node_modules/@foo/bar`
                            !isScoped && pathComponents[pathComponents.length - 3].toLowerCase() === modulesDirName; // `node_modules/foo`
                    });
                if (log)
                    log("Searching for typing names in ".concat(packagesFolderPath, "; all files: ").concat(JSON.stringify(dependencyManifestNames)));
                // Once we have the names of things to look up, we iterate over
                // and either collect their included typings, or add them to the
                // list of typings we need to look up separately.
                for (var _i = 0, dependencyManifestNames_1 = dependencyManifestNames; _i < dependencyManifestNames_1.length; _i++) {
                    var manifestPath_1 = dependencyManifestNames_1[_i];
                    var normalizedFileName = ts.normalizePath(manifestPath_1);
                    var result_1 = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); });
                    var manifest_1 = result_1.config;
                    // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used
                    // to download d.ts files from DefinitelyTyped
                    if (!manifest_1.name) {
                        continue;
                    }
                    var ownTypes = manifest_1.types || manifest_1.typings;
                    if (ownTypes) {
                        var absolutePath = ts.getNormalizedAbsolutePath(ownTypes, ts.getDirectoryPath(normalizedFileName));
                        if (host.fileExists(absolutePath)) {
                            if (log)
                                log("    Package '".concat(manifest_1.name, "' provides its own types."));
                            inferredTypings.set(manifest_1.name, absolutePath);
                        }
                        else {
                            if (log)
                                log("    Package '".concat(manifest_1.name, "' provides its own types but they are missing."));
                        }
                    }
                    else {
                        packageNames.push(manifest_1.name);
                    }
                }
                addInferredTypings(packageNames, "    Found package names");
            }
            /**
             * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js"
             * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred
             * to the 'angular-route' typing name.
             * @param fileNames are the names for source files in the project
             */
            function getTypingNamesFromSourceFileNames(fileNames) {
                var fromFileNames = ts.mapDefined(fileNames, function (j) {
                    if (!ts.hasJSFileExtension(j))
                        return undefined;
                    var inferredTypingName = ts.removeFileExtension(ts.getBaseFileName(j.toLowerCase()));
                    var cleanedTypingName = ts.removeMinAndVersionNumbers(inferredTypingName);
                    return safeList.get(cleanedTypingName);
                });
                if (fromFileNames.length) {
                    addInferredTypings(fromFileNames, "Inferred typings from file names");
                }
                var hasJsxFile = ts.some(fileNames, function (f) { return ts.fileExtensionIs(f, ".jsx" /* Extension.Jsx */); });
                if (hasJsxFile) {
                    if (log)
                        log("Inferred 'react' typings due to presence of '.jsx' extension");
                    addInferredTyping("react");
                }
            }
        }
        JsTyping.discoverTypings = discoverTypings;
        var NameValidationResult;
        (function (NameValidationResult) {
            NameValidationResult[NameValidationResult["Ok"] = 0] = "Ok";
            NameValidationResult[NameValidationResult["EmptyName"] = 1] = "EmptyName";
            NameValidationResult[NameValidationResult["NameTooLong"] = 2] = "NameTooLong";
            NameValidationResult[NameValidationResult["NameStartsWithDot"] = 3] = "NameStartsWithDot";
            NameValidationResult[NameValidationResult["NameStartsWithUnderscore"] = 4] = "NameStartsWithUnderscore";
            NameValidationResult[NameValidationResult["NameContainsNonURISafeCharacters"] = 5] = "NameContainsNonURISafeCharacters";
        })(NameValidationResult = JsTyping.NameValidationResult || (JsTyping.NameValidationResult = {}));
        var maxPackageNameLength = 214;
        /**
         * Validates package name using rules defined at https://docs.npmjs.com/files/package.json
         */
        function validatePackageName(packageName) {
            return validatePackageNameWorker(packageName, /*supportScopedPackage*/ true);
        }
        JsTyping.validatePackageName = validatePackageName;
        function validatePackageNameWorker(packageName, supportScopedPackage) {
            if (!packageName) {
                return 1 /* NameValidationResult.EmptyName */;
            }
            if (packageName.length > maxPackageNameLength) {
                return 2 /* NameValidationResult.NameTooLong */;
            }
            if (packageName.charCodeAt(0) === 46 /* CharacterCodes.dot */) {
                return 3 /* NameValidationResult.NameStartsWithDot */;
            }
            if (packageName.charCodeAt(0) === 95 /* CharacterCodes._ */) {
                return 4 /* NameValidationResult.NameStartsWithUnderscore */;
            }
            // check if name is scope package like: starts with @ and has one '/' in the middle
            // scoped packages are not currently supported
            if (supportScopedPackage) {
                var matches = /^@([^/]+)\/([^/]+)$/.exec(packageName);
                if (matches) {
                    var scopeResult = validatePackageNameWorker(matches[1], /*supportScopedPackage*/ false);
                    if (scopeResult !== 0 /* NameValidationResult.Ok */) {
                        return { name: matches[1], isScopeName: true, result: scopeResult };
                    }
                    var packageResult = validatePackageNameWorker(matches[2], /*supportScopedPackage*/ false);
                    if (packageResult !== 0 /* NameValidationResult.Ok */) {
                        return { name: matches[2], isScopeName: false, result: packageResult };
                    }
                    return 0 /* NameValidationResult.Ok */;
                }
            }
            if (encodeURIComponent(packageName) !== packageName) {
                return 5 /* NameValidationResult.NameContainsNonURISafeCharacters */;
            }
            return 0 /* NameValidationResult.Ok */;
        }
        function renderPackageNameValidationFailure(result, typing) {
            return typeof result === "object" ?
                renderPackageNameValidationFailureWorker(typing, result.result, result.name, result.isScopeName) :
                renderPackageNameValidationFailureWorker(typing, result, typing, /*isScopeName*/ false);
        }
        JsTyping.renderPackageNameValidationFailure = renderPackageNameValidationFailure;
        function renderPackageNameValidationFailureWorker(typing, result, name, isScopeName) {
            var kind = isScopeName ? "Scope" : "Package";
            switch (result) {
                case 1 /* NameValidationResult.EmptyName */:
                    return "'".concat(typing, "':: ").concat(kind, " name '").concat(name, "' cannot be empty");
                case 2 /* NameValidationResult.NameTooLong */:
                    return "'".concat(typing, "':: ").concat(kind, " name '").concat(name, "' should be less than ").concat(maxPackageNameLength, " characters");
                case 3 /* NameValidationResult.NameStartsWithDot */:
                    return "'".concat(typing, "':: ").concat(kind, " name '").concat(name, "' cannot start with '.'");
                case 4 /* NameValidationResult.NameStartsWithUnderscore */:
                    return "'".concat(typing, "':: ").concat(kind, " name '").concat(name, "' cannot start with '_'");
                case 5 /* NameValidationResult.NameContainsNonURISafeCharacters */:
                    return "'".concat(typing, "':: ").concat(kind, " name '").concat(name, "' contains non URI safe characters");
                case 0 /* NameValidationResult.Ok */:
                    return ts.Debug.fail(); // Shouldn't have called this.
                default:
                    throw ts.Debug.assertNever(result);
            }
        }
    })(JsTyping = ts.JsTyping || (ts.JsTyping = {}));
})(ts || (ts = {}));
var ts;
(function (ts) {
    var server;
    (function (server) {
        var LogLevel;
        (function (LogLevel) {
            LogLevel[LogLevel["terse"] = 0] = "terse";
            LogLevel[LogLevel["normal"] = 1] = "normal";
            LogLevel[LogLevel["requestTime"] = 2] = "requestTime";
            LogLevel[LogLevel["verbose"] = 3] = "verbose";
        })(LogLevel = server.LogLevel || (server.LogLevel = {}));
        server.emptyArray = createSortedArray();
        // TODO: Use a const enum (https://github.com/Microsoft/TypeScript/issues/16804)
        var Msg;
        (function (Msg) {
            Msg["Err"] = "Err";
            Msg["Info"] = "Info";
            Msg["Perf"] = "Perf";
        })(Msg = server.Msg || (server.Msg = {}));
        function createInstallTypingsRequest(project, typeAcquisition, unresolvedImports, cachePath) {
            return {
                projectName: project.getProjectName(),
                fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true, /*excludeConfigFiles*/ true).concat(project.getExcludedFiles()),
                compilerOptions: project.getCompilationSettings(),
                watchOptions: project.projectService.getWatchOptions(project),
                typeAcquisition: typeAcquisition,
                unresolvedImports: unresolvedImports,
                projectRootPath: project.getCurrentDirectory(),
                cachePath: cachePath,
                kind: "discover"
            };
        }
        server.createInstallTypingsRequest = createInstallTypingsRequest;
        var Errors;
        (function (Errors) {
            function ThrowNoProject() {
                throw new Error("No Project.");
            }
            Errors.ThrowNoProject = ThrowNoProject;
            function ThrowProjectLanguageServiceDisabled() {
                throw new Error("The project's language service is disabled.");
            }
            Errors.ThrowProjectLanguageServiceDisabled = ThrowProjectLanguageServiceDisabled;
            function ThrowProjectDoesNotContainDocument(fileName, project) {
                throw new Error("Project '".concat(project.getProjectName(), "' does not contain document '").concat(fileName, "'"));
            }
            Errors.ThrowProjectDoesNotContainDocument = ThrowProjectDoesNotContainDocument;
        })(Errors = server.Errors || (server.Errors = {}));
        function toNormalizedPath(fileName) {
            return ts.normalizePath(fileName);
        }
        server.toNormalizedPath = toNormalizedPath;
        function normalizedPathToPath(normalizedPath, currentDirectory, getCanonicalFileName) {
            var f = ts.isRootedDiskPath(normalizedPath) ? normalizedPath : ts.getNormalizedAbsolutePath(normalizedPath, currentDirectory);
            return getCanonicalFileName(f);
        }
        server.normalizedPathToPath = normalizedPathToPath;
        function asNormalizedPath(fileName) {
            return fileName;
        }
        server.asNormalizedPath = asNormalizedPath;
        function createNormalizedPathMap() {
            var map = new ts.Map();
            return {
                get: function (path) {
                    return map.get(path);
                },
                set: function (path, value) {
                    map.set(path, value);
                },
                contains: function (path) {
                    return map.has(path);
                },
                remove: function (path) {
                    map.delete(path);
                }
            };
        }
        server.createNormalizedPathMap = createNormalizedPathMap;
        function isInferredProjectName(name) {
            // POSIX defines /dev/null as a device - there should be no file with this prefix
            return /dev\/null\/inferredProject\d+\*/.test(name);
        }
        server.isInferredProjectName = isInferredProjectName;
        function makeInferredProjectName(counter) {
            return "/dev/null/inferredProject".concat(counter, "*");
        }
        server.makeInferredProjectName = makeInferredProjectName;
        /*@internal*/
        function makeAutoImportProviderProjectName(counter) {
            return "/dev/null/autoImportProviderProject".concat(counter, "*");
        }
        server.makeAutoImportProviderProjectName = makeAutoImportProviderProjectName;
        /*@internal*/
        function makeAuxiliaryProjectName(counter) {
            return "/dev/null/auxiliaryProject".concat(counter, "*");
        }
        server.makeAuxiliaryProjectName = makeAuxiliaryProjectName;
        function createSortedArray() {
            return []; // TODO: GH#19873
        }
        server.createSortedArray = createSortedArray;
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/* @internal */
var ts;
(function (ts) {
    var server;
    (function (server) {
        var ThrottledOperations = /** @class */ (function () {
            function ThrottledOperations(host, logger) {
                this.host = host;
                this.pendingTimeouts = new ts.Map();
                this.logger = logger.hasLevel(server.LogLevel.verbose) ? logger : undefined;
            }
            /**
             * Wait `number` milliseconds and then invoke `cb`.  If, while waiting, schedule
             * is called again with the same `operationId`, cancel this operation in favor
             * of the new one.  (Note that the amount of time the canceled operation had been
             * waiting does not affect the amount of time that the new operation waits.)
             */
            ThrottledOperations.prototype.schedule = function (operationId, delay, cb) {
                var pendingTimeout = this.pendingTimeouts.get(operationId);
                if (pendingTimeout) {
                    // another operation was already scheduled for this id - cancel it
                    this.host.clearTimeout(pendingTimeout);
                }
                // schedule new operation, pass arguments
                this.pendingTimeouts.set(operationId, this.host.setTimeout(ThrottledOperations.run, delay, this, operationId, cb));
                if (this.logger) {
                    this.logger.info("Scheduled: ".concat(operationId).concat(pendingTimeout ? ", Cancelled earlier one" : ""));
                }
            };
            ThrottledOperations.prototype.cancel = function (operationId) {
                var pendingTimeout = this.pendingTimeouts.get(operationId);
                if (!pendingTimeout)
                    return false;
                this.host.clearTimeout(pendingTimeout);
                return this.pendingTimeouts.delete(operationId);
            };
            ThrottledOperations.run = function (self, operationId, cb) {
                ts.perfLogger.logStartScheduledOperation(operationId);
                self.pendingTimeouts.delete(operationId);
                if (self.logger) {
                    self.logger.info("Running: ".concat(operationId));
                }
                cb();
                ts.perfLogger.logStopScheduledOperation();
            };
            return ThrottledOperations;
        }());
        server.ThrottledOperations = ThrottledOperations;
        var GcTimer = /** @class */ (function () {
            function GcTimer(host, delay, logger) {
                this.host = host;
                this.delay = delay;
                this.logger = logger;
            }
            GcTimer.prototype.scheduleCollect = function () {
                if (!this.host.gc || this.timerId !== undefined) {
                    // no global.gc or collection was already scheduled - skip this request
                    return;
                }
                this.timerId = this.host.setTimeout(GcTimer.run, this.delay, this);
            };
            GcTimer.run = function (self) {
                self.timerId = undefined;
                ts.perfLogger.logStartScheduledOperation("GC collect");
                var log = self.logger.hasLevel(server.LogLevel.requestTime);
                var before = log && self.host.getMemoryUsage(); // TODO: GH#18217
                self.host.gc(); // TODO: GH#18217
                if (log) {
                    var after = self.host.getMemoryUsage(); // TODO: GH#18217
                    self.logger.perftrc("GC::before ".concat(before, ", after ").concat(after));
                }
                ts.perfLogger.logStopScheduledOperation();
            };
            return GcTimer;
        }());
        server.GcTimer = GcTimer;
        function getBaseConfigFileName(configFilePath) {
            var base = ts.getBaseFileName(configFilePath);
            return base === "tsconfig.json" || base === "jsconfig.json" ? base : undefined;
        }
        server.getBaseConfigFileName = getBaseConfigFileName;
        function removeSorted(array, remove, compare) {
            if (!array || array.length === 0) {
                return;
            }
            if (array[0] === remove) {
                array.splice(0, 1);
                return;
            }
            var removeIndex = ts.binarySearch(array, remove, ts.identity, compare);
            if (removeIndex >= 0) {
                array.splice(removeIndex, 1);
            }
        }
        server.removeSorted = removeSorted;
        var indentStr = "\n    ";
        function indent(str) {
            return indentStr + str.replace(/\n/g, indentStr);
        }
        server.indent = indent;
        /** Put stringified JSON on the next line, indented. */
        function stringifyIndented(json) {
            return indentStr + JSON.stringify(json);
        }
        server.stringifyIndented = stringifyIndented;
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/* @internal */
var ts;
(function (ts) {
    ts.WatchType.ClosedScriptInfo = "Closed Script info";
    ts.WatchType.ConfigFileForInferredRoot = "Config file for the inferred project root";
    ts.WatchType.NodeModules = "node_modules for closed script infos and package.jsons affecting module specifier cache";
    ts.WatchType.MissingSourceMapFile = "Missing source map file";
    ts.WatchType.NoopConfigFileForInferredRoot = "Noop Config file for the inferred project root";
    ts.WatchType.MissingGeneratedFile = "Missing generated file";
})(ts || (ts = {}));
/* eslint-disable @typescript-eslint/no-unnecessary-qualifier */
/**
 * Declaration module describing the TypeScript Server protocol
 */
var ts;
(function (ts) {
    var server;
    (function (server) {
        var protocol;
        (function (protocol) {
            // NOTE: If updating this, be sure to also update `allCommandNames` in `testRunner/unittests/tsserver/session.ts`.
            var CommandTypes;
            (function (CommandTypes) {
                CommandTypes["JsxClosingTag"] = "jsxClosingTag";
                CommandTypes["Brace"] = "brace";
                /* @internal */
                CommandTypes["BraceFull"] = "brace-full";
                CommandTypes["BraceCompletion"] = "braceCompletion";
                CommandTypes["GetSpanOfEnclosingComment"] = "getSpanOfEnclosingComment";
                CommandTypes["Change"] = "change";
                CommandTypes["Close"] = "close";
                /** @deprecated Prefer CompletionInfo -- see comment on CompletionsResponse */
                CommandTypes["Completions"] = "completions";
                CommandTypes["CompletionInfo"] = "completionInfo";
                /* @internal */
                CommandTypes["CompletionsFull"] = "completions-full";
                CommandTypes["CompletionDetails"] = "completionEntryDetails";
                /* @internal */
                CommandTypes["CompletionDetailsFull"] = "completionEntryDetails-full";
                CommandTypes["CompileOnSaveAffectedFileList"] = "compileOnSaveAffectedFileList";
                CommandTypes["CompileOnSaveEmitFile"] = "compileOnSaveEmitFile";
                CommandTypes["Configure"] = "configure";
                CommandTypes["Definition"] = "definition";
                /* @internal */
                CommandTypes["DefinitionFull"] = "definition-full";
                CommandTypes["DefinitionAndBoundSpan"] = "definitionAndBoundSpan";
                /* @internal */
                CommandTypes["DefinitionAndBoundSpanFull"] = "definitionAndBoundSpan-full";
                CommandTypes["Implementation"] = "implementation";
                /* @internal */
                CommandTypes["ImplementationFull"] = "implementation-full";
                /* @internal */
                CommandTypes["EmitOutput"] = "emit-output";
                CommandTypes["Exit"] = "exit";
                CommandTypes["FileReferences"] = "fileReferences";
                /* @internal */
                CommandTypes["FileReferencesFull"] = "fileReferences-full";
                CommandTypes["Format"] = "format";
                CommandTypes["Formatonkey"] = "formatonkey";
                /* @internal */
                CommandTypes["FormatFull"] = "format-full";
                /* @internal */
                CommandTypes["FormatonkeyFull"] = "formatonkey-full";
                /* @internal */
                CommandTypes["FormatRangeFull"] = "formatRange-full";
                CommandTypes["Geterr"] = "geterr";
                CommandTypes["GeterrForProject"] = "geterrForProject";
                CommandTypes["SemanticDiagnosticsSync"] = "semanticDiagnosticsSync";
                CommandTypes["SyntacticDiagnosticsSync"] = "syntacticDiagnosticsSync";
                CommandTypes["SuggestionDiagnosticsSync"] = "suggestionDiagnosticsSync";
                CommandTypes["NavBar"] = "navbar";
                /* @internal */
                CommandTypes["NavBarFull"] = "navbar-full";
                CommandTypes["Navto"] = "navto";
                /* @internal */
                CommandTypes["NavtoFull"] = "navto-full";
                CommandTypes["NavTree"] = "navtree";
                CommandTypes["NavTreeFull"] = "navtree-full";
                /** @deprecated */
                CommandTypes["Occurrences"] = "occurrences";
                CommandTypes["DocumentHighlights"] = "documentHighlights";
                /* @internal */
                CommandTypes["DocumentHighlightsFull"] = "documentHighlights-full";
                CommandTypes["Open"] = "open";
                CommandTypes["Quickinfo"] = "quickinfo";
                /* @internal */
                CommandTypes["QuickinfoFull"] = "quickinfo-full";
                CommandTypes["References"] = "references";
                /* @internal */
                CommandTypes["ReferencesFull"] = "references-full";
                CommandTypes["Reload"] = "reload";
                CommandTypes["Rename"] = "rename";
                /* @internal */
                CommandTypes["RenameInfoFull"] = "rename-full";
                /* @internal */
                CommandTypes["RenameLocationsFull"] = "renameLocations-full";
                CommandTypes["Saveto"] = "saveto";
                CommandTypes["SignatureHelp"] = "signatureHelp";
                /* @internal */
                CommandTypes["SignatureHelpFull"] = "signatureHelp-full";
                CommandTypes["FindSourceDefinition"] = "findSourceDefinition";
                CommandTypes["Status"] = "status";
                CommandTypes["TypeDefinition"] = "typeDefinition";
                CommandTypes["ProjectInfo"] = "projectInfo";
                CommandTypes["ReloadProjects"] = "reloadProjects";
                CommandTypes["Unknown"] = "unknown";
                CommandTypes["OpenExternalProject"] = "openExternalProject";
                CommandTypes["OpenExternalProjects"] = "openExternalProjects";
                CommandTypes["CloseExternalProject"] = "closeExternalProject";
                /* @internal */
                CommandTypes["SynchronizeProjectList"] = "synchronizeProjectList";
                /* @internal */
                CommandTypes["ApplyChangedToOpenFiles"] = "applyChangedToOpenFiles";
                CommandTypes["UpdateOpen"] = "updateOpen";
                /* @internal */
                CommandTypes["EncodedSyntacticClassificationsFull"] = "encodedSyntacticClassifications-full";
                /* @internal */
                CommandTypes["EncodedSemanticClassificationsFull"] = "encodedSemanticClassifications-full";
                /* @internal */
                CommandTypes["Cleanup"] = "cleanup";
                CommandTypes["GetOutliningSpans"] = "getOutliningSpans";
                /* @internal */
                CommandTypes["GetOutliningSpansFull"] = "outliningSpans";
                CommandTypes["TodoComments"] = "todoComments";
                CommandTypes["Indentation"] = "indentation";
                CommandTypes["DocCommentTemplate"] = "docCommentTemplate";
                /* @internal */
                CommandTypes["CompilerOptionsDiagnosticsFull"] = "compilerOptionsDiagnostics-full";
                /* @internal */
                CommandTypes["NameOrDottedNameSpan"] = "nameOrDottedNameSpan";
                /* @internal */
                CommandTypes["BreakpointStatement"] = "breakpointStatement";
                CommandTypes["CompilerOptionsForInferredProjects"] = "compilerOptionsForInferredProjects";
                CommandTypes["GetCodeFixes"] = "getCodeFixes";
                /* @internal */
                CommandTypes["GetCodeFixesFull"] = "getCodeFixes-full";
                CommandTypes["GetCombinedCodeFix"] = "getCombinedCodeFix";
                /* @internal */
                CommandTypes["GetCombinedCodeFixFull"] = "getCombinedCodeFix-full";
                CommandTypes["ApplyCodeActionCommand"] = "applyCodeActionCommand";
                CommandTypes["GetSupportedCodeFixes"] = "getSupportedCodeFixes";
                CommandTypes["GetApplicableRefactors"] = "getApplicableRefactors";
                CommandTypes["GetEditsForRefactor"] = "getEditsForRefactor";
                /* @internal */
                CommandTypes["GetEditsForRefactorFull"] = "getEditsForRefactor-full";
                CommandTypes["OrganizeImports"] = "organizeImports";
                /* @internal */
                CommandTypes["OrganizeImportsFull"] = "organizeImports-full";
                CommandTypes["GetEditsForFileRename"] = "getEditsForFileRename";
                /* @internal */
                CommandTypes["GetEditsForFileRenameFull"] = "getEditsForFileRename-full";
                CommandTypes["ConfigurePlugin"] = "configurePlugin";
                CommandTypes["SelectionRange"] = "selectionRange";
                /* @internal */
                CommandTypes["SelectionRangeFull"] = "selectionRange-full";
                CommandTypes["ToggleLineComment"] = "toggleLineComment";
                /* @internal */
                CommandTypes["ToggleLineCommentFull"] = "toggleLineComment-full";
                CommandTypes["ToggleMultilineComment"] = "toggleMultilineComment";
                /* @internal */
                CommandTypes["ToggleMultilineCommentFull"] = "toggleMultilineComment-full";
                CommandTypes["CommentSelection"] = "commentSelection";
                /* @internal */
                CommandTypes["CommentSelectionFull"] = "commentSelection-full";
                CommandTypes["UncommentSelection"] = "uncommentSelection";
                /* @internal */
                CommandTypes["UncommentSelectionFull"] = "uncommentSelection-full";
                CommandTypes["PrepareCallHierarchy"] = "prepareCallHierarchy";
                CommandTypes["ProvideCallHierarchyIncomingCalls"] = "provideCallHierarchyIncomingCalls";
                CommandTypes["ProvideCallHierarchyOutgoingCalls"] = "provideCallHierarchyOutgoingCalls";
                CommandTypes["ProvideInlayHints"] = "provideInlayHints";
                // NOTE: If updating this, be sure to also update `allCommandNames` in `testRunner/unittests/tsserver/session.ts`.
            })(CommandTypes = protocol.CommandTypes || (protocol.CommandTypes = {}));
            var WatchFileKind;
            (function (WatchFileKind) {
                WatchFileKind["FixedPollingInterval"] = "FixedPollingInterval";
                WatchFileKind["PriorityPollingInterval"] = "PriorityPollingInterval";
                WatchFileKind["DynamicPriorityPolling"] = "DynamicPriorityPolling";
                WatchFileKind["FixedChunkSizePolling"] = "FixedChunkSizePolling";
                WatchFileKind["UseFsEvents"] = "UseFsEvents";
                WatchFileKind["UseFsEventsOnParentDirectory"] = "UseFsEventsOnParentDirectory";
            })(WatchFileKind = protocol.WatchFileKind || (protocol.WatchFileKind = {}));
            var WatchDirectoryKind;
            (function (WatchDirectoryKind) {
                WatchDirectoryKind["UseFsEvents"] = "UseFsEvents";
                WatchDirectoryKind["FixedPollingInterval"] = "FixedPollingInterval";
                WatchDirectoryKind["DynamicPriorityPolling"] = "DynamicPriorityPolling";
                WatchDirectoryKind["FixedChunkSizePolling"] = "FixedChunkSizePolling";
            })(WatchDirectoryKind = protocol.WatchDirectoryKind || (protocol.WatchDirectoryKind = {}));
            var PollingWatchKind;
            (function (PollingWatchKind) {
                PollingWatchKind["FixedInterval"] = "FixedInterval";
                PollingWatchKind["PriorityInterval"] = "PriorityInterval";
                PollingWatchKind["DynamicPriority"] = "DynamicPriority";
                PollingWatchKind["FixedChunkSize"] = "FixedChunkSize";
            })(PollingWatchKind = protocol.PollingWatchKind || (protocol.PollingWatchKind = {}));
            var CompletionTriggerKind;
            (function (CompletionTriggerKind) {
                /** Completion was triggered by typing an identifier, manual invocation (e.g Ctrl+Space) or via API. */
                CompletionTriggerKind[CompletionTriggerKind["Invoked"] = 1] = "Invoked";
                /** Completion was triggered by a trigger character. */
                CompletionTriggerKind[CompletionTriggerKind["TriggerCharacter"] = 2] = "TriggerCharacter";
                /** Completion was re-triggered as the current completion list is incomplete. */
                CompletionTriggerKind[CompletionTriggerKind["TriggerForIncompleteCompletions"] = 3] = "TriggerForIncompleteCompletions";
            })(CompletionTriggerKind = protocol.CompletionTriggerKind || (protocol.CompletionTriggerKind = {}));
            var IndentStyle;
            (function (IndentStyle) {
                IndentStyle["None"] = "None";
                IndentStyle["Block"] = "Block";
                IndentStyle["Smart"] = "Smart";
            })(IndentStyle = protocol.IndentStyle || (protocol.IndentStyle = {}));
            var SemicolonPreference;
            (function (SemicolonPreference) {
                SemicolonPreference["Ignore"] = "ignore";
                SemicolonPreference["Insert"] = "insert";
                SemicolonPreference["Remove"] = "remove";
            })(SemicolonPreference = protocol.SemicolonPreference || (protocol.SemicolonPreference = {}));
            var JsxEmit;
            (function (JsxEmit) {
                JsxEmit["None"] = "None";
                JsxEmit["Preserve"] = "Preserve";
                JsxEmit["ReactNative"] = "ReactNative";
                JsxEmit["React"] = "React";
            })(JsxEmit = protocol.JsxEmit || (protocol.JsxEmit = {}));
            var ModuleKind;
            (function (ModuleKind) {
                ModuleKind["None"] = "None";
                ModuleKind["CommonJS"] = "CommonJS";
                ModuleKind["AMD"] = "AMD";
                ModuleKind["UMD"] = "UMD";
                ModuleKind["System"] = "System";
                ModuleKind["ES6"] = "ES6";
                ModuleKind["ES2015"] = "ES2015";
                ModuleKind["ESNext"] = "ESNext";
            })(ModuleKind = protocol.ModuleKind || (protocol.ModuleKind = {}));
            var ModuleResolutionKind;
            (function (ModuleResolutionKind) {
                ModuleResolutionKind["Classic"] = "Classic";
                ModuleResolutionKind["Node"] = "Node";
            })(ModuleResolutionKind = protocol.ModuleResolutionKind || (protocol.ModuleResolutionKind = {}));
            var NewLineKind;
            (function (NewLineKind) {
                NewLineKind["Crlf"] = "Crlf";
                NewLineKind["Lf"] = "Lf";
            })(NewLineKind = protocol.NewLineKind || (protocol.NewLineKind = {}));
            var ScriptTarget;
            (function (ScriptTarget) {
                ScriptTarget["ES3"] = "ES3";
                ScriptTarget["ES5"] = "ES5";
                ScriptTarget["ES6"] = "ES6";
                ScriptTarget["ES2015"] = "ES2015";
                ScriptTarget["ES2016"] = "ES2016";
                ScriptTarget["ES2017"] = "ES2017";
                ScriptTarget["ES2018"] = "ES2018";
                ScriptTarget["ES2019"] = "ES2019";
                ScriptTarget["ES2020"] = "ES2020";
                ScriptTarget["ES2021"] = "ES2021";
                ScriptTarget["ES2022"] = "ES2022";
                ScriptTarget["ESNext"] = "ESNext";
            })(ScriptTarget = protocol.ScriptTarget || (protocol.ScriptTarget = {}));
            var ClassificationType;
            (function (ClassificationType) {
                ClassificationType[ClassificationType["comment"] = 1] = "comment";
                ClassificationType[ClassificationType["identifier"] = 2] = "identifier";
                ClassificationType[ClassificationType["keyword"] = 3] = "keyword";
                ClassificationType[ClassificationType["numericLiteral"] = 4] = "numericLiteral";
                ClassificationType[ClassificationType["operator"] = 5] = "operator";
                ClassificationType[ClassificationType["stringLiteral"] = 6] = "stringLiteral";
                ClassificationType[ClassificationType["regularExpressionLiteral"] = 7] = "regularExpressionLiteral";
                ClassificationType[ClassificationType["whiteSpace"] = 8] = "whiteSpace";
                ClassificationType[ClassificationType["text"] = 9] = "text";
                ClassificationType[ClassificationType["punctuation"] = 10] = "punctuation";
                ClassificationType[ClassificationType["className"] = 11] = "className";
                ClassificationType[ClassificationType["enumName"] = 12] = "enumName";
                ClassificationType[ClassificationType["interfaceName"] = 13] = "interfaceName";
                ClassificationType[ClassificationType["moduleName"] = 14] = "moduleName";
                ClassificationType[ClassificationType["typeParameterName"] = 15] = "typeParameterName";
                ClassificationType[ClassificationType["typeAliasName"] = 16] = "typeAliasName";
                ClassificationType[ClassificationType["parameterName"] = 17] = "parameterName";
                ClassificationType[ClassificationType["docCommentTagName"] = 18] = "docCommentTagName";
                ClassificationType[ClassificationType["jsxOpenTagName"] = 19] = "jsxOpenTagName";
                ClassificationType[ClassificationType["jsxCloseTagName"] = 20] = "jsxCloseTagName";
                ClassificationType[ClassificationType["jsxSelfClosingTagName"] = 21] = "jsxSelfClosingTagName";
                ClassificationType[ClassificationType["jsxAttribute"] = 22] = "jsxAttribute";
                ClassificationType[ClassificationType["jsxText"] = 23] = "jsxText";
                ClassificationType[ClassificationType["jsxAttributeStringLiteralValue"] = 24] = "jsxAttributeStringLiteralValue";
                ClassificationType[ClassificationType["bigintLiteral"] = 25] = "bigintLiteral";
            })(ClassificationType = protocol.ClassificationType || (protocol.ClassificationType = {}));
        })(protocol = server.protocol || (server.protocol = {}));
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
var ts;
(function (ts) {
    var server;
    (function (server) {
        /* @internal */
        var TextStorage = /** @class */ (function () {
            function TextStorage(host, info, initialVersion) {
                this.host = host;
                this.info = info;
                /**
                 * True if the text is for the file thats open in the editor
                 */
                this.isOpen = false;
                /**
                 * True if the text present is the text from the file on the disk
                 */
                this.ownFileText = false;
                /**
                 * True when reloading contents of file from the disk is pending
                 */
                this.pendingReloadFromDisk = false;
                this.version = initialVersion || { svc: 0, text: 0 };
            }
            TextStorage.prototype.getVersion = function () {
                return this.svc
                    ? "SVC-".concat(this.version.svc, "-").concat(this.svc.getSnapshotVersion())
                    : "Text-".concat(this.version.text);
            };
            TextStorage.prototype.hasScriptVersionCache_TestOnly = function () {
                return this.svc !== undefined;
            };
            TextStorage.prototype.useScriptVersionCache_TestOnly = function () {
                this.switchToScriptVersionCache();
            };
            TextStorage.prototype.resetSourceMapInfo = function () {
                this.info.sourceFileLike = undefined;
                this.info.closeSourceMapFileWatcher();
                this.info.sourceMapFilePath = undefined;
                this.info.declarationInfoPath = undefined;
                this.info.sourceInfos = undefined;
                this.info.documentPositionMapper = undefined;
            };
            /** Public for testing */
            TextStorage.prototype.useText = function (newText) {
                this.svc = undefined;
                this.text = newText;
                this.lineMap = undefined;
                this.fileSize = undefined;
                this.resetSourceMapInfo();
                this.version.text++;
            };
            TextStorage.prototype.edit = function (start, end, newText) {
                this.switchToScriptVersionCache().edit(start, end - start, newText);
                this.ownFileText = false;
                this.text = undefined;
                this.lineMap = undefined;
                this.fileSize = undefined;
                this.resetSourceMapInfo();
            };
            /**
             * Set the contents as newText
             * returns true if text changed
             */
            TextStorage.prototype.reload = function (newText) {
                ts.Debug.assert(newText !== undefined);
                // Reload always has fresh content
                this.pendingReloadFromDisk = false;
                // If text changed set the text
                // This also ensures that if we had switched to version cache,
                // we are switching back to text.
                // The change to version cache will happen when needed
                // Thus avoiding the computation if there are no changes
                if (this.text !== newText) {
                    this.useText(newText);
                    // We cant guarantee new text is own file text
                    this.ownFileText = false;
                    return true;
                }
                return false;
            };
            /**
             * Reads the contents from tempFile(if supplied) or own file and sets it as contents
             * returns true if text changed
             */
            TextStorage.prototype.reloadWithFileText = function (tempFileName) {
                var _a = this.getFileTextAndSize(tempFileName), newText = _a.text, fileSize = _a.fileSize;
                var reloaded = this.reload(newText);
                this.fileSize = fileSize; // NB: after reload since reload clears it
                this.ownFileText = !tempFileName || tempFileName === this.info.fileName;
                return reloaded;
            };
            /**
             * Reloads the contents from the file if there is no pending reload from disk or the contents of file are same as file text
             * returns true if text changed
             */
            TextStorage.prototype.reloadFromDisk = function () {
                if (!this.pendingReloadFromDisk && !this.ownFileText) {
                    return this.reloadWithFileText();
                }
                return false;
            };
            TextStorage.prototype.delayReloadFromFileIntoText = function () {
                this.pendingReloadFromDisk = true;
            };
            /**
             * For telemetry purposes, we would like to be able to report the size of the file.
             * However, we do not want telemetry to require extra file I/O so we report a size
             * that may be stale (e.g. may not reflect change made on disk since the last reload).
             * NB: Will read from disk if the file contents have never been loaded because
             * telemetry falsely indicating size 0 would be counter-productive.
             */
            TextStorage.prototype.getTelemetryFileSize = function () {
                return !!this.fileSize
                    ? this.fileSize
                    : !!this.text // Check text before svc because its length is cheaper
                        ? this.text.length // Could be wrong if this.pendingReloadFromDisk
                        : !!this.svc
                            ? this.svc.getSnapshot().getLength() // Could be wrong if this.pendingReloadFromDisk
                            : this.getSnapshot().getLength(); // Should be strictly correct
            };
            TextStorage.prototype.getSnapshot = function () {
                return this.useScriptVersionCacheIfValidOrOpen()
                    ? this.svc.getSnapshot()
                    : ts.ScriptSnapshot.fromString(this.getOrLoadText());
            };
            TextStorage.prototype.getAbsolutePositionAndLineText = function (line) {
                return this.switchToScriptVersionCache().getAbsolutePositionAndLineText(line);
            };
            /**
             *  @param line 0 based index
             */
            TextStorage.prototype.lineToTextSpan = function (line) {
                if (!this.useScriptVersionCacheIfValidOrOpen()) {
                    var lineMap = this.getLineMap();
                    var start = lineMap[line]; // -1 since line is 1-based
                    var end = line + 1 < lineMap.length ? lineMap[line + 1] : this.text.length;
                    return ts.createTextSpanFromBounds(start, end);
                }
                return this.svc.lineToTextSpan(line);
            };
            /**
             * @param line 1 based index
             * @param offset 1 based index
             */
            TextStorage.prototype.lineOffsetToPosition = function (line, offset, allowEdits) {
                if (!this.useScriptVersionCacheIfValidOrOpen()) {
                    return ts.computePositionOfLineAndCharacter(this.getLineMap(), line - 1, offset - 1, this.text, allowEdits);
                }
                // TODO: assert this offset is actually on the line
                return this.svc.lineOffsetToPosition(line, offset);
            };
            TextStorage.prototype.positionToLineOffset = function (position) {
                if (!this.useScriptVersionCacheIfValidOrOpen()) {
                    var _a = ts.computeLineAndCharacterOfPosition(this.getLineMap(), position), line = _a.line, character = _a.character;
                    return { line: line + 1, offset: character + 1 };
                }
                return this.svc.positionToLineOffset(position);
            };
            TextStorage.prototype.getFileTextAndSize = function (tempFileName) {
                var _this = this;
                var text;
                var fileName = tempFileName || this.info.fileName;
                var getText = function () { return text === undefined ? (text = _this.host.readFile(fileName) || "") : text; };
                // Only non typescript files have size limitation
                if (!ts.hasTSFileExtension(this.info.fileName)) {
                    var fileSize = this.host.getFileSize ? this.host.getFileSize(fileName) : getText().length;
                    if (fileSize > server.maxFileSize) {
                        ts.Debug.assert(!!this.info.containingProjects.length);
                        var service = this.info.containingProjects[0].projectService;
                        service.logger.info("Skipped loading contents of large file ".concat(fileName, " for info ").concat(this.info.fileName, ": fileSize: ").concat(fileSize));
                        this.info.containingProjects[0].projectService.sendLargeFileReferencedEvent(fileName, fileSize);
                        return { text: "", fileSize: fileSize };
                    }
                }
                return { text: getText() };
            };
            TextStorage.prototype.switchToScriptVersionCache = function () {
                if (!this.svc || this.pendingReloadFromDisk) {
                    this.svc = server.ScriptVersionCache.fromString(this.getOrLoadText());
                    this.version.svc++;
                }
                return this.svc;
            };
            TextStorage.prototype.useScriptVersionCacheIfValidOrOpen = function () {
                // If this is open script, use the cache
                if (this.isOpen) {
                    return this.switchToScriptVersionCache();
                }
                // If there is pending reload from the disk then, reload the text
                if (this.pendingReloadFromDisk) {
                    this.reloadWithFileText();
                }
                // At this point if svc is present it's valid
                return this.svc;
            };
            TextStorage.prototype.getOrLoadText = function () {
                if (this.text === undefined || this.pendingReloadFromDisk) {
                    ts.Debug.assert(!this.svc || this.pendingReloadFromDisk, "ScriptVersionCache should not be set when reloading from disk");
                    this.reloadWithFileText();
                }
                return this.text;
            };
            TextStorage.prototype.getLineMap = function () {
                ts.Debug.assert(!this.svc, "ScriptVersionCache should not be set");
                return this.lineMap || (this.lineMap = ts.computeLineStarts(this.getOrLoadText()));
            };
            TextStorage.prototype.getLineInfo = function () {
                var _this = this;
                if (this.svc) {
                    return {
                        getLineCount: function () { return _this.svc.getLineCount(); },
                        getLineText: function (line) { return _this.svc.getAbsolutePositionAndLineText(line + 1).lineText; }
                    };
                }
                var lineMap = this.getLineMap();
                return ts.getLineInfo(this.text, lineMap);
            };
            return TextStorage;
        }());
        server.TextStorage = TextStorage;
        function isDynamicFileName(fileName) {
            return fileName[0] === "^" ||
                ((ts.stringContains(fileName, "walkThroughSnippet:/") || ts.stringContains(fileName, "untitled:/")) &&
                    ts.getBaseFileName(fileName)[0] === "^") ||
                (ts.stringContains(fileName, ":^") && !ts.stringContains(fileName, ts.directorySeparator));
        }
        server.isDynamicFileName = isDynamicFileName;
        var ScriptInfo = /** @class */ (function () {
            function ScriptInfo(host, fileName, scriptKind, hasMixedContent, path, initialVersion) {
                this.host = host;
                this.fileName = fileName;
                this.scriptKind = scriptKind;
                this.hasMixedContent = hasMixedContent;
                this.path = path;
                /**
                 * All projects that include this file
                 */
                this.containingProjects = [];
                this.isDynamic = isDynamicFileName(fileName);
                this.textStorage = new TextStorage(host, this, initialVersion);
                if (hasMixedContent || this.isDynamic) {
                    this.textStorage.reload("");
                    this.realpath = this.path;
                }
                this.scriptKind = scriptKind
                    ? scriptKind
                    : ts.getScriptKindFromFileName(fileName);
            }
            /*@internal*/
            ScriptInfo.prototype.getVersion = function () {
                return this.textStorage.version;
            };
            /*@internal*/
            ScriptInfo.prototype.getTelemetryFileSize = function () {
                return this.textStorage.getTelemetryFileSize();
            };
            /*@internal*/
            ScriptInfo.prototype.isDynamicOrHasMixedContent = function () {
                return this.hasMixedContent || this.isDynamic;
            };
            ScriptInfo.prototype.isScriptOpen = function () {
                return this.textStorage.isOpen;
            };
            ScriptInfo.prototype.open = function (newText) {
                this.textStorage.isOpen = true;
                if (newText !== undefined &&
                    this.textStorage.reload(newText)) {
                    // reload new contents only if the existing contents changed
                    this.markContainingProjectsAsDirty();
                }
            };
            ScriptInfo.prototype.close = function (fileExists) {
                if (fileExists === void 0) { fileExists = true; }
                this.textStorage.isOpen = false;
                if (this.isDynamicOrHasMixedContent() || !fileExists) {
                    if (this.textStorage.reload("")) {
                        this.markContainingProjectsAsDirty();
                    }
                }
                else if (this.textStorage.reloadFromDisk()) {
                    this.markContainingProjectsAsDirty();
                }
            };
            ScriptInfo.prototype.getSnapshot = function () {
                return this.textStorage.getSnapshot();
            };
            ScriptInfo.prototype.ensureRealPath = function () {
                if (this.realpath === undefined) {
                    // Default is just the path
                    this.realpath = this.path;
                    if (this.host.realpath) {
                        ts.Debug.assert(!!this.containingProjects.length);
                        var project = this.containingProjects[0];
                        var realpath = this.host.realpath(this.path);
                        if (realpath) {
                            this.realpath = project.toPath(realpath);
                            // If it is different from this.path, add to the map
                            if (this.realpath !== this.path) {
                                project.projectService.realpathToScriptInfos.add(this.realpath, this); // TODO: GH#18217
                            }
                        }
                    }
                }
            };
            /*@internal*/
            ScriptInfo.prototype.getRealpathIfDifferent = function () {
                return this.realpath && this.realpath !== this.path ? this.realpath : undefined;
            };
            /**
             * @internal
             * Does not compute realpath; uses precomputed result. Use `ensureRealPath`
             * first if a definite result is needed.
             */
            ScriptInfo.prototype.isSymlink = function () {
                return this.realpath && this.realpath !== this.path;
            };
            ScriptInfo.prototype.getFormatCodeSettings = function () { return this.formatSettings; };
            ScriptInfo.prototype.getPreferences = function () { return this.preferences; };
            ScriptInfo.prototype.attachToProject = function (project) {
                var isNew = !this.isAttached(project);
                if (isNew) {
                    this.containingProjects.push(project);
                    if (!project.getCompilerOptions().preserveSymlinks) {
                        this.ensureRealPath();
                    }
                    project.onFileAddedOrRemoved(this.isSymlink());
                }
                return isNew;
            };
            ScriptInfo.prototype.isAttached = function (project) {
                // unrolled for common cases
                switch (this.containingProjects.length) {
                    case 0: return false;
                    case 1: return this.containingProjects[0] === project;
                    case 2: return this.containingProjects[0] === project || this.containingProjects[1] === project;
                    default: return ts.contains(this.containingProjects, project);
                }
            };
            ScriptInfo.prototype.detachFromProject = function (project) {
                // unrolled for common cases
                switch (this.containingProjects.length) {
                    case 0:
                        return;
                    case 1:
                        if (this.containingProjects[0] === project) {
                            project.onFileAddedOrRemoved(this.isSymlink());
                            this.containingProjects.pop();
                        }
                        break;
                    case 2:
                        if (this.containingProjects[0] === project) {
                            project.onFileAddedOrRemoved(this.isSymlink());
                            this.containingProjects[0] = this.containingProjects.pop();
                        }
                        else if (this.containingProjects[1] === project) {
                            project.onFileAddedOrRemoved(this.isSymlink());
                            this.containingProjects.pop();
                        }
                        break;
                    default:
                        if (ts.unorderedRemoveItem(this.containingProjects, project)) {
                            project.onFileAddedOrRemoved(this.isSymlink());
                        }
                        break;
                }
            };
            ScriptInfo.prototype.detachAllProjects = function () {
                for (var _i = 0, _a = this.containingProjects; _i < _a.length; _i++) {
                    var p = _a[_i];
                    if (server.isConfiguredProject(p)) {
                        p.getCachedDirectoryStructureHost().addOrDeleteFile(this.fileName, this.path, ts.FileWatcherEventKind.Deleted);
                    }
                    var existingRoot = p.getRootFilesMap().get(this.path);
                    // detach is unnecessary since we'll clean the list of containing projects anyways
                    p.removeFile(this, /*fileExists*/ false, /*detachFromProjects*/ false);
                    p.onFileAddedOrRemoved(this.isSymlink());
                    // If the info was for the external or configured project's root,
                    // add missing file as the root
                    if (existingRoot && !server.isInferredProject(p)) {
                        p.addMissingFileRoot(existingRoot.fileName);
                    }
                }
                ts.clear(this.containingProjects);
            };
            ScriptInfo.prototype.getDefaultProject = function () {
                switch (this.containingProjects.length) {
                    case 0:
                        return server.Errors.ThrowNoProject();
                    case 1:
                        return ensurePrimaryProjectKind(this.containingProjects[0]);
                    default:
                        // If this file belongs to multiple projects, below is the order in which default project is used
                        // - for open script info, its default configured project during opening is default if info is part of it
                        // - first configured project of which script info is not a source of project reference redirect
                        // - first configured project
                        // - first external project
                        // - first inferred project
                        var firstExternalProject = void 0;
                        var firstConfiguredProject = void 0;
                        var firstInferredProject = void 0;
                        var firstNonSourceOfProjectReferenceRedirect = void 0;
                        var defaultConfiguredProject = void 0;
                        for (var index = 0; index < this.containingProjects.length; index++) {
                            var project = this.containingProjects[index];
                            if (server.isConfiguredProject(project)) {
                                if (!project.isSourceOfProjectReferenceRedirect(this.fileName)) {
                                    // If we havent found default configuredProject and
                                    // its not the last one, find it and use that one if there
                                    if (defaultConfiguredProject === undefined &&
                                        index !== this.containingProjects.length - 1) {
                                        defaultConfiguredProject = project.projectService.findDefaultConfiguredProject(this) || false;
                                    }
                                    if (defaultConfiguredProject === project)
                                        return project;
                                    if (!firstNonSourceOfProjectReferenceRedirect)
                                        firstNonSourceOfProjectReferenceRedirect = project;
                                }
                                if (!firstConfiguredProject)
                                    firstConfiguredProject = project;
                            }
                            else if (!firstExternalProject && server.isExternalProject(project)) {
                                firstExternalProject = project;
                            }
                            else if (!firstInferredProject && server.isInferredProject(project)) {
                                firstInferredProject = project;
                            }
                        }
                        return ensurePrimaryProjectKind(defaultConfiguredProject ||
                            firstNonSourceOfProjectReferenceRedirect ||
                            firstConfiguredProject ||
                            firstExternalProject ||
                            firstInferredProject);
                }
            };
            ScriptInfo.prototype.registerFileUpdate = function () {
                for (var _i = 0, _a = this.containingProjects; _i < _a.length; _i++) {
                    var p = _a[_i];
                    p.registerFileUpdate(this.path);
                }
            };
            ScriptInfo.prototype.setOptions = function (formatSettings, preferences) {
                if (formatSettings) {
                    if (!this.formatSettings) {
                        this.formatSettings = ts.getDefaultFormatCodeSettings(this.host.newLine);
                        ts.assign(this.formatSettings, formatSettings);
                    }
                    else {
                        this.formatSettings = __assign(__assign({}, this.formatSettings), formatSettings);
                    }
                }
                if (preferences) {
                    if (!this.preferences) {
                        this.preferences = ts.emptyOptions;
                    }
                    this.preferences = __assign(__assign({}, this.preferences), preferences);
                }
            };
            ScriptInfo.prototype.getLatestVersion = function () {
                // Ensure we have updated snapshot to give back latest version
                this.textStorage.getSnapshot();
                return this.textStorage.getVersion();
            };
            ScriptInfo.prototype.saveTo = function (fileName) {
                this.host.writeFile(fileName, ts.getSnapshotText(this.textStorage.getSnapshot()));
            };
            /*@internal*/
            ScriptInfo.prototype.delayReloadNonMixedContentFile = function () {
                ts.Debug.assert(!this.isDynamicOrHasMixedContent());
                this.textStorage.delayReloadFromFileIntoText();
                this.markContainingProjectsAsDirty();
            };
            ScriptInfo.prototype.reloadFromFile = function (tempFileName) {
                if (this.isDynamicOrHasMixedContent()) {
                    this.textStorage.reload("");
                    this.markContainingProjectsAsDirty();
                    return true;
                }
                else {
                    if (this.textStorage.reloadWithFileText(tempFileName)) {
                        this.markContainingProjectsAsDirty();
                        return true;
                    }
                }
                return false;
            };
            /*@internal*/
            ScriptInfo.prototype.getAbsolutePositionAndLineText = function (line) {
                return this.textStorage.getAbsolutePositionAndLineText(line);
            };
            ScriptInfo.prototype.editContent = function (start, end, newText) {
                this.textStorage.edit(start, end, newText);
                this.markContainingProjectsAsDirty();
            };
            ScriptInfo.prototype.markContainingProjectsAsDirty = function () {
                for (var _i = 0, _a = this.containingProjects; _i < _a.length; _i++) {
                    var p = _a[_i];
                    p.markFileAsDirty(this.path);
                }
            };
            ScriptInfo.prototype.isOrphan = function () {
                return !ts.forEach(this.containingProjects, function (p) { return !p.isOrphan(); });
            };
            /*@internal*/
            ScriptInfo.prototype.isContainedByBackgroundProject = function () {
                return ts.some(this.containingProjects, function (p) { return p.projectKind === server.ProjectKind.AutoImportProvider || p.projectKind === server.ProjectKind.Auxiliary; });
            };
            /**
             *  @param line 1 based index
             */
            ScriptInfo.prototype.lineToTextSpan = function (line) {
                return this.textStorage.lineToTextSpan(line);
            };
            ScriptInfo.prototype.lineOffsetToPosition = function (line, offset, allowEdits) {
                return this.textStorage.lineOffsetToPosition(line, offset, allowEdits);
            };
            ScriptInfo.prototype.positionToLineOffset = function (position) {
                failIfInvalidPosition(position);
                var location = this.textStorage.positionToLineOffset(position);
                failIfInvalidLocation(location);
                return location;
            };
            ScriptInfo.prototype.isJavaScript = function () {
                return this.scriptKind === 1 /* ScriptKind.JS */ || this.scriptKind === 2 /* ScriptKind.JSX */;
            };
            /*@internal*/
            ScriptInfo.prototype.getLineInfo = function () {
                return this.textStorage.getLineInfo();
            };
            /*@internal*/
            ScriptInfo.prototype.closeSourceMapFileWatcher = function () {
                if (this.sourceMapFilePath && !ts.isString(this.sourceMapFilePath)) {
                    ts.closeFileWatcherOf(this.sourceMapFilePath);
                    this.sourceMapFilePath = undefined;
                }
            };
            return ScriptInfo;
        }());
        server.ScriptInfo = ScriptInfo;
        /**
         * Throws an error if `project` is an AutoImportProvider or AuxiliaryProject,
         * which are used in the background by other Projects and should never be
         * reported as the default project for a ScriptInfo.
         */
        function ensurePrimaryProjectKind(project) {
            if (!project || project.projectKind === server.ProjectKind.AutoImportProvider || project.projectKind === server.ProjectKind.Auxiliary) {
                return server.Errors.ThrowNoProject();
            }
            return project;
        }
        function failIfInvalidPosition(position) {
            ts.Debug.assert(typeof position === "number", "Expected position ".concat(position, " to be a number."));
            ts.Debug.assert(position >= 0, "Expected position to be non-negative.");
        }
        function failIfInvalidLocation(location) {
            ts.Debug.assert(typeof location.line === "number", "Expected line ".concat(location.line, " to be a number."));
            ts.Debug.assert(typeof location.offset === "number", "Expected offset ".concat(location.offset, " to be a number."));
            ts.Debug.assert(location.line > 0, "Expected line to be non-".concat(location.line === 0 ? "zero" : "negative"));
            ts.Debug.assert(location.offset > 0, "Expected offset to be non-".concat(location.offset === 0 ? "zero" : "negative"));
        }
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
var ts;
(function (ts) {
    var server;
    (function (server) {
        server.nullTypingsInstaller = {
            isKnownTypesPackageName: ts.returnFalse,
            // Should never be called because we never provide a types registry.
            installPackage: ts.notImplemented,
            enqueueInstallTypingsRequest: ts.noop,
            attach: ts.noop,
            onProjectClosed: ts.noop,
            globalTypingsCacheLocation: undefined // TODO: GH#18217
        };
        function setIsEqualTo(arr1, arr2) {
            if (arr1 === arr2) {
                return true;
            }
            if ((arr1 || server.emptyArray).length === 0 && (arr2 || server.emptyArray).length === 0) {
                return true;
            }
            var set = new ts.Map();
            var unique = 0;
            for (var _i = 0, _a = arr1; _i < _a.length; _i++) {
                var v = _a[_i];
                if (set.get(v) !== true) {
                    set.set(v, true);
                    unique++;
                }
            }
            for (var _b = 0, _c = arr2; _b < _c.length; _b++) {
                var v = _c[_b];
                var isSet = set.get(v);
                if (isSet === undefined) {
                    return false;
                }
                if (isSet === true) {
                    set.set(v, false);
                    unique--;
                }
            }
            return unique === 0;
        }
        function typeAcquisitionChanged(opt1, opt2) {
            return opt1.enable !== opt2.enable ||
                !setIsEqualTo(opt1.include, opt2.include) ||
                !setIsEqualTo(opt1.exclude, opt2.exclude);
        }
        function compilerOptionsChanged(opt1, opt2) {
            // TODO: add more relevant properties
            return ts.getAllowJSCompilerOption(opt1) !== ts.getAllowJSCompilerOption(opt2);
        }
        function unresolvedImportsChanged(imports1, imports2) {
            if (imports1 === imports2) {
                return false;
            }
            return !ts.arrayIsEqualTo(imports1, imports2);
        }
        /*@internal*/
        var TypingsCache = /** @class */ (function () {
            function TypingsCache(installer) {
                this.installer = installer;
                this.perProjectCache = new ts.Map();
            }
            TypingsCache.prototype.isKnownTypesPackageName = function (name) {
                return this.installer.isKnownTypesPackageName(name);
            };
            TypingsCache.prototype.installPackage = function (options) {
                return this.installer.installPackage(options);
            };
            TypingsCache.prototype.enqueueInstallTypingsForProject = function (project, unresolvedImports, forceRefresh) {
                var typeAcquisition = project.getTypeAcquisition();
                if (!typeAcquisition || !typeAcquisition.enable) {
                    return;
                }
                var entry = this.perProjectCache.get(project.getProjectName());
                if (forceRefresh ||
                    !entry ||
                    typeAcquisitionChanged(typeAcquisition, entry.typeAcquisition) ||
                    compilerOptionsChanged(project.getCompilationSettings(), entry.compilerOptions) ||
                    unresolvedImportsChanged(unresolvedImports, entry.unresolvedImports)) {
                    // Note: entry is now poisoned since it does not really contain typings for a given combination of compiler options\typings options.
                    // instead it acts as a placeholder to prevent issuing multiple requests
                    this.perProjectCache.set(project.getProjectName(), {
                        compilerOptions: project.getCompilationSettings(),
                        typeAcquisition: typeAcquisition,
                        typings: entry ? entry.typings : server.emptyArray,
                        unresolvedImports: unresolvedImports,
                        poisoned: true
                    });
                    // something has been changed, issue a request to update typings
                    this.installer.enqueueInstallTypingsRequest(project, typeAcquisition, unresolvedImports);
                }
            };
            TypingsCache.prototype.updateTypingsForProject = function (projectName, compilerOptions, typeAcquisition, unresolvedImports, newTypings) {
                var typings = ts.sort(newTypings);
                this.perProjectCache.set(projectName, {
                    compilerOptions: compilerOptions,
                    typeAcquisition: typeAcquisition,
                    typings: typings,
                    unresolvedImports: unresolvedImports,
                    poisoned: false
                });
                return !typeAcquisition || !typeAcquisition.enable ? server.emptyArray : typings;
            };
            TypingsCache.prototype.onProjectClosed = function (project) {
                this.perProjectCache.delete(project.getProjectName());
                this.installer.onProjectClosed(project);
            };
            return TypingsCache;
        }());
        server.TypingsCache = TypingsCache;
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
var ts;
(function (ts) {
    var server;
    (function (server) {
        var ProjectKind;
        (function (ProjectKind) {
            ProjectKind[ProjectKind["Inferred"] = 0] = "Inferred";
            ProjectKind[ProjectKind["Configured"] = 1] = "Configured";
            ProjectKind[ProjectKind["External"] = 2] = "External";
            ProjectKind[ProjectKind["AutoImportProvider"] = 3] = "AutoImportProvider";
            ProjectKind[ProjectKind["Auxiliary"] = 4] = "Auxiliary";
        })(ProjectKind = server.ProjectKind || (server.ProjectKind = {}));
        /* @internal */
        function countEachFileTypes(infos, includeSizes) {
            if (includeSizes === void 0) { includeSizes = false; }
            var result = {
                js: 0, jsSize: 0,
                jsx: 0, jsxSize: 0,
                ts: 0, tsSize: 0,
                tsx: 0, tsxSize: 0,
                dts: 0, dtsSize: 0,
                deferred: 0, deferredSize: 0,
            };
            for (var _i = 0, infos_1 = infos; _i < infos_1.length; _i++) {
                var info = infos_1[_i];
                var fileSize = includeSizes ? info.getTelemetryFileSize() : 0;
                switch (info.scriptKind) {
                    case 1 /* ScriptKind.JS */:
                        result.js += 1;
                        result.jsSize += fileSize;
                        break;
                    case 2 /* ScriptKind.JSX */:
                        result.jsx += 1;
                        result.jsxSize += fileSize;
                        break;
                    case 3 /* ScriptKind.TS */:
                        if (ts.isDeclarationFileName(info.fileName)) {
                            result.dts += 1;
                            result.dtsSize += fileSize;
                        }
                        else {
                            result.ts += 1;
                            result.tsSize += fileSize;
                        }
                        break;
                    case 4 /* ScriptKind.TSX */:
                        result.tsx += 1;
                        result.tsxSize += fileSize;
                        break;
                    case 7 /* ScriptKind.Deferred */:
                        result.deferred += 1;
                        result.deferredSize += fileSize;
                        break;
                }
            }
            return result;
        }
        server.countEachFileTypes = countEachFileTypes;
        function hasOneOrMoreJsAndNoTsFiles(project) {
            var counts = countEachFileTypes(project.getScriptInfos());
            return counts.js > 0 && counts.ts === 0 && counts.tsx === 0;
        }
        function allRootFilesAreJsOrDts(project) {
            var counts = countEachFileTypes(project.getRootScriptInfos());
            return counts.ts === 0 && counts.tsx === 0;
        }
        server.allRootFilesAreJsOrDts = allRootFilesAreJsOrDts;
        function allFilesAreJsOrDts(project) {
            var counts = countEachFileTypes(project.getScriptInfos());
            return counts.ts === 0 && counts.tsx === 0;
        }
        server.allFilesAreJsOrDts = allFilesAreJsOrDts;
        /* @internal */
        function hasNoTypeScriptSource(fileNames) {
            return !fileNames.some(function (fileName) { return (ts.fileExtensionIs(fileName, ".ts" /* Extension.Ts */) && !ts.isDeclarationFileName(fileName)) || ts.fileExtensionIs(fileName, ".tsx" /* Extension.Tsx */); });
        }
        server.hasNoTypeScriptSource = hasNoTypeScriptSource;
        function isGeneratedFileWatcher(watch) {
            return watch.generatedFilePath !== undefined;
        }
        var Project = /** @class */ (function () {
            /*@internal*/
            function Project(
            /*@internal*/ projectName, projectKind, projectService, documentRegistry, hasExplicitListOfFiles, lastFileExceededProgramSize, compilerOptions, compileOnSaveEnabled, watchOptions, directoryStructureHost, currentDirectory) {
                var _this = this;
                this.projectName = projectName;
                this.projectKind = projectKind;
                this.projectService = projectService;
                this.documentRegistry = documentRegistry;
                this.compilerOptions = compilerOptions;
                this.compileOnSaveEnabled = compileOnSaveEnabled;
                this.watchOptions = watchOptions;
                this.rootFiles = [];
                this.rootFilesMap = new ts.Map();
                this.plugins = [];
                /*@internal*/
                /**
                 * This is map from files to unresolved imports in it
                 * Maop does not contain entries for files that do not have unresolved imports
                 * This helps in containing the set of files to invalidate
                 */
                this.cachedUnresolvedImportsPerFile = new ts.Map();
                /*@internal*/
                this.hasAddedorRemovedFiles = false;
                /*@internal*/
                this.hasAddedOrRemovedSymlinks = false;
                /**
                 * Last version that was reported.
                 */
                this.lastReportedVersion = 0;
                /**
                 * Current project's program version. (incremented everytime new program is created that is not complete reuse from the old one)
                 * This property is changed in 'updateGraph' based on the set of files in program
                 */
                this.projectProgramVersion = 0;
                /**
                 * Current version of the project state. It is changed when:
                 * - new root file was added/removed
                 * - edit happen in some file that is currently included in the project.
                 * This property is different from projectStructureVersion since in most cases edits don't affect set of files in the project
                 */
                this.projectStateVersion = 0;
                this.isInitialLoadPending = ts.returnFalse;
                /*@internal*/
                this.dirty = false;
                /*@internal*/
                this.typingFiles = server.emptyArray;
                /*@internal*/
                this.moduleSpecifierCache = server.createModuleSpecifierCache(this);
                /*@internal*/
                this.globalCacheResolutionModuleName = ts.JsTyping.nonRelativeModuleNameForTypingCache;
                this.directoryStructureHost = directoryStructureHost;
                this.currentDirectory = this.projectService.getNormalizedAbsolutePath(currentDirectory || "");
                this.getCanonicalFileName = this.projectService.toCanonicalFileName;
                this.cancellationToken = new ts.ThrottledCancellationToken(this.projectService.cancellationToken, this.projectService.throttleWaitMilliseconds);
                if (!this.compilerOptions) {
                    this.compilerOptions = ts.getDefaultCompilerOptions();
                    this.compilerOptions.allowNonTsExtensions = true;
                    this.compilerOptions.allowJs = true;
                }
                else if (hasExplicitListOfFiles || ts.getAllowJSCompilerOption(this.compilerOptions) || this.projectService.hasDeferredExtension()) {
                    // If files are listed explicitly or allowJs is specified, allow all extensions
                    this.compilerOptions.allowNonTsExtensions = true;
                }
                switch (projectService.serverMode) {
                    case ts.LanguageServiceMode.Semantic:
                        this.languageServiceEnabled = true;
                        break;
                    case ts.LanguageServiceMode.PartialSemantic:
                        this.languageServiceEnabled = true;
                        this.compilerOptions.noResolve = true;
                        this.compilerOptions.types = [];
                        break;
                    case ts.LanguageServiceMode.Syntactic:
                        this.languageServiceEnabled = false;
                        this.compilerOptions.noResolve = true;
                        this.compilerOptions.types = [];
                        break;
                    default:
                        ts.Debug.assertNever(projectService.serverMode);
                }
                this.setInternalCompilerOptionsForEmittingJsFiles();
                var host = this.projectService.host;
                if (this.projectService.logger.loggingEnabled()) {
                    this.trace = function (s) { return _this.writeLog(s); };
                }
                else if (host.trace) {
                    this.trace = function (s) { return host.trace(s); };
                }
                this.realpath = ts.maybeBind(host, host.realpath);
                // Use the current directory as resolution root only if the project created using current directory string
                this.resolutionCache = ts.createResolutionCache(this, currentDirectory && this.currentDirectory, 
                /*logChangesWhenResolvingModule*/ true);
                this.languageService = ts.createLanguageService(this, this.documentRegistry, this.projectService.serverMode);
                if (lastFileExceededProgramSize) {
                    this.disableLanguageService(lastFileExceededProgramSize);
                }
                this.markAsDirty();
                if (projectKind !== ProjectKind.AutoImportProvider) {
                    this.projectService.pendingEnsureProjectForOpenFiles = true;
                }
            }
            /*@internal*/
            Project.prototype.getResolvedProjectReferenceToRedirect = function (_fileName) {
                return undefined;
            };
            Project.prototype.isNonTsProject = function () {
                server.updateProjectIfDirty(this);
                return allFilesAreJsOrDts(this);
            };
            Project.prototype.isJsOnlyProject = function () {
                server.updateProjectIfDirty(this);
                return hasOneOrMoreJsAndNoTsFiles(this);
            };
            Project.resolveModule = function (moduleName, initialDir, host, log, logErrors) {
                var resolvedPath = ts.normalizeSlashes(host.resolvePath(ts.combinePaths(initialDir, "node_modules")));
                log("Loading ".concat(moduleName, " from ").concat(initialDir, " (resolved to ").concat(resolvedPath, ")"));
                var result = host.require(resolvedPath, moduleName); // TODO: GH#18217
                if (result.error) {
                    var err = result.error.stack || result.error.message || JSON.stringify(result.error);
                    (logErrors || log)("Failed to load module '".concat(moduleName, "' from ").concat(resolvedPath, ": ").concat(err));
                    return undefined;
                }
                return result.module;
            };
            Project.prototype.isKnownTypesPackageName = function (name) {
                return this.typingsCache.isKnownTypesPackageName(name);
            };
            Project.prototype.installPackage = function (options) {
                return this.typingsCache.installPackage(__assign(__assign({}, options), { projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) }));
            };
            /*@internal*/
            Project.prototype.getGlobalTypingsCacheLocation = function () {
                return this.getGlobalCache();
            };
            Object.defineProperty(Project.prototype, "typingsCache", {
                get: function () {
                    return this.projectService.typingsCache;
                },
                enumerable: false,
                configurable: true
            });
            /*@internal*/
            Project.prototype.getSymlinkCache = function () {
                if (!this.symlinks) {
                    this.symlinks = ts.createSymlinkCache(this.getCurrentDirectory(), this.getCanonicalFileName);
                }
                if (this.program && !this.symlinks.hasProcessedResolutions()) {
                    this.symlinks.setSymlinksFromResolutions(this.program.getSourceFiles(), this.program.getResolvedTypeReferenceDirectives());
                }
                return this.symlinks;
            };
            // Method of LanguageServiceHost
            Project.prototype.getCompilationSettings = function () {
                return this.compilerOptions;
            };
            // Method to support public API
            Project.prototype.getCompilerOptions = function () {
                return this.getCompilationSettings();
            };
            Project.prototype.getNewLine = function () {
                return this.projectService.host.newLine;
            };
            Project.prototype.getProjectVersion = function () {
                return this.projectStateVersion.toString();
            };
            Project.prototype.getProjectReferences = function () {
                return undefined;
            };
            Project.prototype.getScriptFileNames = function () {
                var _this = this;
                if (!this.rootFiles) {
                    return ts.emptyArray;
                }
                var result;
                this.rootFilesMap.forEach(function (value) {
                    if (_this.languageServiceEnabled || (value.info && value.info.isScriptOpen())) {
                        // if language service is disabled - process only files that are open
                        (result || (result = [])).push(value.fileName);
                    }
                });
                return ts.addRange(result, this.typingFiles) || ts.emptyArray;
            };
            Project.prototype.getOrCreateScriptInfoAndAttachToProject = function (fileName) {
                var scriptInfo = this.projectService.getOrCreateScriptInfoNotOpenedByClient(fileName, this.currentDirectory, this.directoryStructureHost);
                if (scriptInfo) {
                    var existingValue = this.rootFilesMap.get(scriptInfo.path);
                    if (existingValue && existingValue.info !== scriptInfo) {
                        // This was missing path earlier but now the file exists. Update the root
                        this.rootFiles.push(scriptInfo);
                        existingValue.info = scriptInfo;
                    }
                    scriptInfo.attachToProject(this);
                }
                return scriptInfo;
            };
            Project.prototype.getScriptKind = function (fileName) {
                var info = this.getOrCreateScriptInfoAndAttachToProject(fileName);
                return (info && info.scriptKind); // TODO: GH#18217
            };
            Project.prototype.getScriptVersion = function (filename) {
                // Don't attach to the project if version is asked
                var info = this.projectService.getOrCreateScriptInfoNotOpenedByClient(filename, this.currentDirectory, this.directoryStructureHost);
                return (info && info.getLatestVersion()); // TODO: GH#18217
            };
            Project.prototype.getScriptSnapshot = function (filename) {
                var scriptInfo = this.getOrCreateScriptInfoAndAttachToProject(filename);
                if (scriptInfo) {
                    return scriptInfo.getSnapshot();
                }
            };
            Project.prototype.getCancellationToken = function () {
                return this.cancellationToken;
            };
            Project.prototype.getCurrentDirectory = function () {
                return this.currentDirectory;
            };
            Project.prototype.getDefaultLibFileName = function () {
                var nodeModuleBinDir = ts.getDirectoryPath(ts.normalizePath(this.projectService.getExecutingFilePath()));
                return ts.combinePaths(nodeModuleBinDir, ts.getDefaultLibFileName(this.compilerOptions));
            };
            Project.prototype.useCaseSensitiveFileNames = function () {
                return this.projectService.host.useCaseSensitiveFileNames;
            };
            Project.prototype.readDirectory = function (path, extensions, exclude, include, depth) {
                return this.directoryStructureHost.readDirectory(path, extensions, exclude, include, depth);
            };
            Project.prototype.readFile = function (fileName) {
                return this.projectService.host.readFile(fileName);
            };
            Project.prototype.writeFile = function (fileName, content) {
                return this.projectService.host.writeFile(fileName, content);
            };
            Project.prototype.fileExists = function (file) {
                // As an optimization, don't hit the disks for files we already know don't exist
                // (because we're watching for their creation).
                var path = this.toPath(file);
                return !this.isWatchedMissingFile(path) && this.directoryStructureHost.fileExists(file);
            };
            Project.prototype.resolveModuleNames = function (moduleNames, containingFile, reusedNames, redirectedReference, _options, containingSourceFile) {
                return this.resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference, containingSourceFile);
            };
            Project.prototype.getModuleResolutionCache = function () {
                return this.resolutionCache.getModuleResolutionCache();
            };
            Project.prototype.getResolvedModuleWithFailedLookupLocationsFromCache = function (moduleName, containingFile, resolutionMode) {
                return this.resolutionCache.getResolvedModuleWithFailedLookupLocationsFromCache(moduleName, containingFile, resolutionMode);
            };
            Project.prototype.resolveTypeReferenceDirectives = function (typeDirectiveNames, containingFile, redirectedReference, _options, containingFileMode) {
                return this.resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference, containingFileMode);
            };
            Project.prototype.directoryExists = function (path) {
                return this.directoryStructureHost.directoryExists(path); // TODO: GH#18217
            };
            Project.prototype.getDirectories = function (path) {
                return this.directoryStructureHost.getDirectories(path); // TODO: GH#18217
            };
            /*@internal*/
            Project.prototype.getCachedDirectoryStructureHost = function () {
                return undefined; // TODO: GH#18217
            };
            /*@internal*/
            Project.prototype.toPath = function (fileName) {
                return ts.toPath(fileName, this.currentDirectory, this.projectService.toCanonicalFileName);
            };
            /*@internal*/
            Project.prototype.watchDirectoryOfFailedLookupLocation = function (directory, cb, flags) {
                return this.projectService.watchFactory.watchDirectory(directory, cb, flags, this.projectService.getWatchOptions(this), ts.WatchType.FailedLookupLocations, this);
            };
            /*@internal*/
            Project.prototype.clearInvalidateResolutionOfFailedLookupTimer = function () {
                return this.projectService.throttledOperations.cancel("".concat(this.getProjectName(), "FailedLookupInvalidation"));
            };
            /*@internal*/
            Project.prototype.scheduleInvalidateResolutionsOfFailedLookupLocations = function () {
                var _this = this;
                this.projectService.throttledOperations.schedule("".concat(this.getProjectName(), "FailedLookupInvalidation"), /*delay*/ 1000, function () {
                    if (_this.resolutionCache.invalidateResolutionsOfFailedLookupLocations()) {
                        _this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(_this);
                    }
                });
            };
            /*@internal*/
            Project.prototype.invalidateResolutionsOfFailedLookupLocations = function () {
                if (this.clearInvalidateResolutionOfFailedLookupTimer() &&
                    this.resolutionCache.invalidateResolutionsOfFailedLookupLocations()) {
                    this.markAsDirty();
                    this.projectService.delayEnsureProjectForOpenFiles();
                }
            };
            /*@internal*/
            Project.prototype.onInvalidatedResolution = function () {
                this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this);
            };
            /*@internal*/
            Project.prototype.watchTypeRootsDirectory = function (directory, cb, flags) {
                return this.projectService.watchFactory.watchDirectory(directory, cb, flags, this.projectService.getWatchOptions(this), ts.WatchType.TypeRoots, this);
            };
            /*@internal*/
            Project.prototype.hasChangedAutomaticTypeDirectiveNames = function () {
                return this.resolutionCache.hasChangedAutomaticTypeDirectiveNames();
            };
            /*@internal*/
            Project.prototype.onChangedAutomaticTypeDirectiveNames = function () {
                this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this);
            };
            /*@internal*/
            Project.prototype.getGlobalCache = function () {
                return this.getTypeAcquisition().enable ? this.projectService.typingsInstaller.globalTypingsCacheLocation : undefined;
            };
            /*@internal*/
            Project.prototype.fileIsOpen = function (filePath) {
                return this.projectService.openFiles.has(filePath);
            };
            /*@internal*/
            Project.prototype.writeLog = function (s) {
                this.projectService.logger.info(s);
            };
            Project.prototype.log = function (s) {
                this.writeLog(s);
            };
            Project.prototype.error = function (s) {
                this.projectService.logger.msg(s, server.Msg.Err);
            };
            Project.prototype.setInternalCompilerOptionsForEmittingJsFiles = function () {
                if (this.projectKind === ProjectKind.Inferred || this.projectKind === ProjectKind.External) {
                    this.compilerOptions.noEmitForJsFiles = true;
                }
            };
            /**
             * Get the errors that dont have any file name associated
             */
            Project.prototype.getGlobalProjectErrors = function () {
                return ts.filter(this.projectErrors, function (diagnostic) { return !diagnostic.file; }) || server.emptyArray;
            };
            /**
             * Get all the project errors
             */
            Project.prototype.getAllProjectErrors = function () {
                return this.projectErrors || server.emptyArray;
            };
            Project.prototype.setProjectErrors = function (projectErrors) {
                this.projectErrors = projectErrors;
            };
            Project.prototype.getLanguageService = function (ensureSynchronized) {
                if (ensureSynchronized === void 0) { ensureSynchronized = true; }
                if (ensureSynchronized) {
                    server.updateProjectIfDirty(this);
                }
                return this.languageService;
            };
            /** @internal */
            Project.prototype.getSourceMapper = function () {
                return this.getLanguageService().getSourceMapper();
            };
            /** @internal */
            Project.prototype.clearSourceMapperCache = function () {
                this.languageService.clearSourceMapperCache();
            };
            /*@internal*/
            Project.prototype.getDocumentPositionMapper = function (generatedFileName, sourceFileName) {
                return this.projectService.getDocumentPositionMapper(this, generatedFileName, sourceFileName);
            };
            /*@internal*/
            Project.prototype.getSourceFileLike = function (fileName) {
                return this.projectService.getSourceFileLike(fileName, this);
            };
            /*@internal*/
            Project.prototype.shouldEmitFile = function (scriptInfo) {
                return scriptInfo &&
                    !scriptInfo.isDynamicOrHasMixedContent() &&
                    !this.program.isSourceOfProjectReferenceRedirect(scriptInfo.path);
            };
            Project.prototype.getCompileOnSaveAffectedFileList = function (scriptInfo) {
                var _this = this;
                if (!this.languageServiceEnabled) {
                    return [];
                }
                server.updateProjectIfDirty(this);
                this.builderState = ts.BuilderState.create(this.program, this.projectService.toCanonicalFileName, this.builderState, /*disableUseFileVersionAsSignature*/ true);
                return ts.mapDefined(ts.BuilderState.getFilesAffectedBy(this.builderState, this.program, scriptInfo.path, this.cancellationToken, ts.maybeBind(this.projectService.host, this.projectService.host.createHash)), function (sourceFile) { return _this.shouldEmitFile(_this.projectService.getScriptInfoForPath(sourceFile.path)) ? sourceFile.fileName : undefined; });
            };
            /**
             * Returns true if emit was conducted
             */
            Project.prototype.emitFile = function (scriptInfo, writeFile) {
                if (!this.languageServiceEnabled || !this.shouldEmitFile(scriptInfo)) {
                    return { emitSkipped: true, diagnostics: server.emptyArray };
                }
                var _a = this.getLanguageService().getEmitOutput(scriptInfo.fileName), emitSkipped = _a.emitSkipped, diagnostics = _a.diagnostics, outputFiles = _a.outputFiles;
                if (!emitSkipped) {
                    for (var _i = 0, outputFiles_1 = outputFiles; _i < outputFiles_1.length; _i++) {
                        var outputFile = outputFiles_1[_i];
                        var outputFileAbsoluteFileName = ts.getNormalizedAbsolutePath(outputFile.name, this.currentDirectory);
                        writeFile(outputFileAbsoluteFileName, outputFile.text, outputFile.writeByteOrderMark);
                    }
                    // Update the signature
                    if (this.builderState && ts.getEmitDeclarations(this.compilerOptions)) {
                        var dtsFiles = outputFiles.filter(function (f) { return ts.isDeclarationFileName(f.name); });
                        if (dtsFiles.length === 1) {
                            var sourceFile = this.program.getSourceFile(scriptInfo.fileName);
                            var signature = this.projectService.host.createHash ?
                                this.projectService.host.createHash(dtsFiles[0].text) :
                                ts.generateDjb2Hash(dtsFiles[0].text);
                            ts.BuilderState.updateSignatureOfFile(this.builderState, signature, sourceFile.resolvedPath);
                        }
                    }
                }
                return { emitSkipped: emitSkipped, diagnostics: diagnostics };
            };
            Project.prototype.enableLanguageService = function () {
                if (this.languageServiceEnabled || this.projectService.serverMode === ts.LanguageServiceMode.Syntactic) {
                    return;
                }
                this.languageServiceEnabled = true;
                this.lastFileExceededProgramSize = undefined;
                this.projectService.onUpdateLanguageServiceStateForProject(this, /*languageServiceEnabled*/ true);
            };
            Project.prototype.disableLanguageService = function (lastFileExceededProgramSize) {
                if (!this.languageServiceEnabled) {
                    return;
                }
                ts.Debug.assert(this.projectService.serverMode !== ts.LanguageServiceMode.Syntactic);
                this.languageService.cleanupSemanticCache();
                this.languageServiceEnabled = false;
                this.lastFileExceededProgramSize = lastFileExceededProgramSize;
                this.builderState = undefined;
                if (this.autoImportProviderHost) {
                    this.autoImportProviderHost.close();
                }
                this.autoImportProviderHost = undefined;
                this.resolutionCache.closeTypeRootsWatch();
                this.clearGeneratedFileWatch();
                this.projectService.onUpdateLanguageServiceStateForProject(this, /*languageServiceEnabled*/ false);
            };
            Project.prototype.getProjectName = function () {
                return this.projectName;
            };
            Project.prototype.removeLocalTypingsFromTypeAcquisition = function (newTypeAcquisition) {
                if (!newTypeAcquisition || !newTypeAcquisition.include) {
                    // Nothing to filter out, so just return as-is
                    return newTypeAcquisition;
                }
                return __assign(__assign({}, newTypeAcquisition), { include: this.removeExistingTypings(newTypeAcquisition.include) });
            };
            Project.prototype.getExternalFiles = function () {
                var _this = this;
                return ts.sort(ts.flatMap(this.plugins, function (plugin) {
                    if (typeof plugin.module.getExternalFiles !== "function")
                        return;
                    try {
                        return plugin.module.getExternalFiles(_this);
                    }
                    catch (e) {
                        _this.projectService.logger.info("A plugin threw an exception in getExternalFiles: ".concat(e));
                        if (e.stack) {
                            _this.projectService.logger.info(e.stack);
                        }
                    }
                }));
            };
            Project.prototype.getSourceFile = function (path) {
                if (!this.program) {
                    return undefined;
                }
                return this.program.getSourceFileByPath(path);
            };
            /* @internal */
            Project.prototype.getSourceFileOrConfigFile = function (path) {
                var options = this.program.getCompilerOptions();
                return path === options.configFilePath ? options.configFile : this.getSourceFile(path);
            };
            Project.prototype.close = function () {
                var _this = this;
                if (this.program) {
                    // if we have a program - release all files that are enlisted in program but arent root
                    // The releasing of the roots happens later
                    // The project could have pending update remaining and hence the info could be in the files but not in program graph
                    for (var _i = 0, _a = this.program.getSourceFiles(); _i < _a.length; _i++) {
                        var f = _a[_i];
                        this.detachScriptInfoIfNotRoot(f.fileName);
                    }
                    this.program.forEachResolvedProjectReference(function (ref) {
                        return _this.detachScriptInfoFromProject(ref.sourceFile.fileName);
                    });
                }
                // Release external files
                ts.forEach(this.externalFiles, function (externalFile) { return _this.detachScriptInfoIfNotRoot(externalFile); });
                // Always remove root files from the project
                for (var _b = 0, _c = this.rootFiles; _b < _c.length; _b++) {
                    var root = _c[_b];
                    root.detachFromProject(this);
                }
                this.projectService.pendingEnsureProjectForOpenFiles = true;
                this.rootFiles = undefined;
                this.rootFilesMap = undefined;
                this.externalFiles = undefined;
                this.program = undefined;
                this.builderState = undefined;
                this.resolutionCache.clear();
                this.resolutionCache = undefined;
                this.cachedUnresolvedImportsPerFile = undefined;
                this.moduleSpecifierCache = undefined;
                this.directoryStructureHost = undefined;
                this.exportMapCache = undefined;
                this.projectErrors = undefined;
                // Clean up file watchers waiting for missing files
                if (this.missingFilesMap) {
                    ts.clearMap(this.missingFilesMap, ts.closeFileWatcher);
                    this.missingFilesMap = undefined;
                }
                this.clearGeneratedFileWatch();
                this.clearInvalidateResolutionOfFailedLookupTimer();
                if (this.autoImportProviderHost) {
                    this.autoImportProviderHost.close();
                }
                this.autoImportProviderHost = undefined;
                if (this.noDtsResolutionProject) {
                    this.noDtsResolutionProject.close();
                }
                this.noDtsResolutionProject = undefined;
                // signal language service to release source files acquired from document registry
                this.languageService.dispose();
                this.languageService = undefined;
            };
            Project.prototype.detachScriptInfoIfNotRoot = function (uncheckedFilename) {
                var info = this.projectService.getScriptInfo(uncheckedFilename);
                // We might not find the script info in case its not associated with the project any more
                // and project graph was not updated (eg delayed update graph in case of files changed/deleted on the disk)
                if (info && !this.isRoot(info)) {
                    info.detachFromProject(this);
                }
            };
            Project.prototype.isClosed = function () {
                return this.rootFiles === undefined;
            };
            Project.prototype.hasRoots = function () {
                return this.rootFiles && this.rootFiles.length > 0;
            };
            /*@internal*/
            Project.prototype.isOrphan = function () {
                return false;
            };
            Project.prototype.getRootFiles = function () {
                return this.rootFiles && this.rootFiles.map(function (info) { return info.fileName; });
            };
            /*@internal*/
            Project.prototype.getRootFilesMap = function () {
                return this.rootFilesMap;
            };
            Project.prototype.getRootScriptInfos = function () {
                return this.rootFiles;
            };
            Project.prototype.getScriptInfos = function () {
                var _this = this;
                if (!this.languageServiceEnabled) {
                    // if language service is not enabled - return just root files
                    return this.rootFiles;
                }
                return ts.map(this.program.getSourceFiles(), function (sourceFile) {
                    var scriptInfo = _this.projectService.getScriptInfoForPath(sourceFile.resolvedPath);
                    ts.Debug.assert(!!scriptInfo, "getScriptInfo", function () { return "scriptInfo for a file '".concat(sourceFile.fileName, "' Path: '").concat(sourceFile.path, "' / '").concat(sourceFile.resolvedPath, "' is missing."); });
                    return scriptInfo;
                });
            };
            Project.prototype.getExcludedFiles = function () {
                return server.emptyArray;
            };
            Project.prototype.getFileNames = function (excludeFilesFromExternalLibraries, excludeConfigFiles) {
                if (!this.program) {
                    return [];
                }
                if (!this.languageServiceEnabled) {
                    // if language service is disabled assume that all files in program are root files + default library
                    var rootFiles = this.getRootFiles();
                    if (this.compilerOptions) {
                        var defaultLibrary = ts.getDefaultLibFilePath(this.compilerOptions);
                        if (defaultLibrary) {
                            (rootFiles || (rootFiles = [])).push(server.asNormalizedPath(defaultLibrary));
                        }
                    }
                    return rootFiles;
                }
                var result = [];
                for (var _i = 0, _a = this.program.getSourceFiles(); _i < _a.length; _i++) {
                    var f = _a[_i];
                    if (excludeFilesFromExternalLibraries && this.program.isSourceFileFromExternalLibrary(f)) {
                        continue;
                    }
                    result.push(server.asNormalizedPath(f.fileName));
                }
                if (!excludeConfigFiles) {
                    var configFile = this.program.getCompilerOptions().configFile;
                    if (configFile) {
                        result.push(server.asNormalizedPath(configFile.fileName));
                        if (configFile.extendedSourceFiles) {
                            for (var _b = 0, _c = configFile.extendedSourceFiles; _b < _c.length; _b++) {
                                var f = _c[_b];
                                result.push(server.asNormalizedPath(f));
                            }
                        }
                    }
                }
                return result;
            };
            /* @internal */
            Project.prototype.getFileNamesWithRedirectInfo = function (includeProjectReferenceRedirectInfo) {
                var _this = this;
                return this.getFileNames().map(function (fileName) { return ({
                    fileName: fileName,
                    isSourceOfProjectReferenceRedirect: includeProjectReferenceRedirectInfo && _this.isSourceOfProjectReferenceRedirect(fileName)
                }); });
            };
            Project.prototype.hasConfigFile = function (configFilePath) {
                if (this.program && this.languageServiceEnabled) {
                    var configFile = this.program.getCompilerOptions().configFile;
                    if (configFile) {
                        if (configFilePath === server.asNormalizedPath(configFile.fileName)) {
                            return true;
                        }
                        if (configFile.extendedSourceFiles) {
                            for (var _i = 0, _a = configFile.extendedSourceFiles; _i < _a.length; _i++) {
                                var f = _a[_i];
                                if (configFilePath === server.asNormalizedPath(f)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
                return false;
            };
            Project.prototype.containsScriptInfo = function (info) {
                if (this.isRoot(info))
                    return true;
                if (!this.program)
                    return false;
                var file = this.program.getSourceFileByPath(info.path);
                return !!file && file.resolvedPath === info.path;
            };
            Project.prototype.containsFile = function (filename, requireOpen) {
                var info = this.projectService.getScriptInfoForNormalizedPath(filename);
                if (info && (info.isScriptOpen() || !requireOpen)) {
                    return this.containsScriptInfo(info);
                }
                return false;
            };
            Project.prototype.isRoot = function (info) {
                var _a;
                return this.rootFilesMap && ((_a = this.rootFilesMap.get(info.path)) === null || _a === void 0 ? void 0 : _a.info) === info;
            };
            // add a root file to project
            Project.prototype.addRoot = function (info, fileName) {
                ts.Debug.assert(!this.isRoot(info));
                this.rootFiles.push(info);
                this.rootFilesMap.set(info.path, { fileName: fileName || info.fileName, info: info });
                info.attachToProject(this);
                this.markAsDirty();
            };
            // add a root file that doesnt exist on host
            Project.prototype.addMissingFileRoot = function (fileName) {
                var path = this.projectService.toPath(fileName);
                this.rootFilesMap.set(path, { fileName: fileName });
                this.markAsDirty();
            };
            Project.prototype.removeFile = function (info, fileExists, detachFromProject) {
                if (this.isRoot(info)) {
                    this.removeRoot(info);
                }
                if (fileExists) {
                    // If file is present, just remove the resolutions for the file
                    this.resolutionCache.removeResolutionsOfFile(info.path);
                }
                else {
                    this.resolutionCache.invalidateResolutionOfFile(info.path);
                }
                this.cachedUnresolvedImportsPerFile.delete(info.path);
                if (detachFromProject) {
                    info.detachFromProject(this);
                }
                this.markAsDirty();
            };
            Project.prototype.registerFileUpdate = function (fileName) {
                (this.updatedFileNames || (this.updatedFileNames = new ts.Set())).add(fileName);
            };
            /*@internal*/
            Project.prototype.markFileAsDirty = function (changedFile) {
                this.markAsDirty();
                if (this.exportMapCache && !this.exportMapCache.isEmpty()) {
                    (this.changedFilesForExportMapCache || (this.changedFilesForExportMapCache = new ts.Set())).add(changedFile);
                }
            };
            Project.prototype.markAsDirty = function () {
                if (!this.dirty) {
                    this.projectStateVersion++;
                    this.dirty = true;
                }
            };
            /*@internal*/
            Project.prototype.onAutoImportProviderSettingsChanged = function () {
                var _a;
                if (this.autoImportProviderHost === false) {
                    this.autoImportProviderHost = undefined;
                }
                else {
                    (_a = this.autoImportProviderHost) === null || _a === void 0 ? void 0 : _a.markAsDirty();
                }
            };
            /*@internal*/
            Project.prototype.onPackageJsonChange = function (packageJsonPath) {
                var _a;
                if ((_a = this.packageJsonsForAutoImport) === null || _a === void 0 ? void 0 : _a.has(packageJsonPath)) {
                    this.moduleSpecifierCache.clear();
                    if (this.autoImportProviderHost) {
                        this.autoImportProviderHost.markAsDirty();
                    }
                }
            };
            /* @internal */
            Project.prototype.onFileAddedOrRemoved = function (isSymlink) {
                this.hasAddedorRemovedFiles = true;
                if (isSymlink) {
                    this.hasAddedOrRemovedSymlinks = true;
                }
            };
            /* @internal */
            Project.prototype.onDiscoveredSymlink = function () {
                this.hasAddedOrRemovedSymlinks = true;
            };
            /**
             * Updates set of files that contribute to this project
             * @returns: true if set of files in the project stays the same and false - otherwise.
             */
            Project.prototype.updateGraph = function () {
                var _a;
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "updateGraph", { name: this.projectName, kind: ProjectKind[this.projectKind] });
                ts.perfLogger.logStartUpdateGraph();
                this.resolutionCache.startRecordingFilesWithChangedResolutions();
                var hasNewProgram = this.updateGraphWorker();
                var hasAddedorRemovedFiles = this.hasAddedorRemovedFiles;
                this.hasAddedorRemovedFiles = false;
                this.hasAddedOrRemovedSymlinks = false;
                var changedFiles = this.resolutionCache.finishRecordingFilesWithChangedResolutions() || server.emptyArray;
                for (var _i = 0, changedFiles_1 = changedFiles; _i < changedFiles_1.length; _i++) {
                    var file = changedFiles_1[_i];
                    // delete cached information for changed files
                    this.cachedUnresolvedImportsPerFile.delete(file);
                }
                // update builder only if language service is enabled
                // otherwise tell it to drop its internal state
                if (this.languageServiceEnabled && this.projectService.serverMode === ts.LanguageServiceMode.Semantic) {
                    // 1. no changes in structure, no changes in unresolved imports - do nothing
                    // 2. no changes in structure, unresolved imports were changed - collect unresolved imports for all files
                    // (can reuse cached imports for files that were not changed)
                    // 3. new files were added/removed, but compilation settings stays the same - collect unresolved imports for all new/modified files
                    // (can reuse cached imports for files that were not changed)
                    // 4. compilation settings were changed in the way that might affect module resolution - drop all caches and collect all data from the scratch
                    if (hasNewProgram || changedFiles.length) {
                        this.lastCachedUnresolvedImportsList = getUnresolvedImports(this.program, this.cachedUnresolvedImportsPerFile);
                    }
                    this.projectService.typingsCache.enqueueInstallTypingsForProject(this, this.lastCachedUnresolvedImportsList, hasAddedorRemovedFiles);
                }
                else {
                    this.lastCachedUnresolvedImportsList = undefined;
                }
                var isFirstProgramLoad = this.projectProgramVersion === 0 && hasNewProgram;
                if (hasNewProgram) {
                    this.projectProgramVersion++;
                }
                if (hasAddedorRemovedFiles) {
                    if (!this.autoImportProviderHost)
                        this.autoImportProviderHost = undefined;
                    (_a = this.autoImportProviderHost) === null || _a === void 0 ? void 0 : _a.markAsDirty();
                }
                if (isFirstProgramLoad) {
                    // Preload auto import provider so it's not created during completions request
                    this.getPackageJsonAutoImportProvider();
                }
                ts.perfLogger.logStopUpdateGraph();
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
                return !hasNewProgram;
            };
            /*@internal*/
            Project.prototype.updateTypingFiles = function (typingFiles) {
                var _this = this;
                if (ts.enumerateInsertsAndDeletes(typingFiles, this.typingFiles, ts.getStringComparer(!this.useCaseSensitiveFileNames()), 
                /*inserted*/ ts.noop, function (removed) { return _this.detachScriptInfoFromProject(removed); })) {
                    // If typing files changed, then only schedule project update
                    this.typingFiles = typingFiles;
                    // Invalidate files with unresolved imports
                    this.resolutionCache.setFilesWithInvalidatedNonRelativeUnresolvedImports(this.cachedUnresolvedImportsPerFile);
                    this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(this);
                }
            };
            /* @internal */
            Project.prototype.getCurrentProgram = function () {
                return this.program;
            };
            Project.prototype.removeExistingTypings = function (include) {
                var existing = ts.getAutomaticTypeDirectiveNames(this.getCompilerOptions(), this.directoryStructureHost);
                return include.filter(function (i) { return existing.indexOf(i) < 0; });
            };
            Project.prototype.updateGraphWorker = function () {
                var _this = this;
                var oldProgram = this.program;
                ts.Debug.assert(!this.isClosed(), "Called update graph worker of closed project");
                this.writeLog("Starting updateGraphWorker: Project: ".concat(this.getProjectName()));
                var start = ts.timestamp();
                this.hasInvalidatedResolution = this.resolutionCache.createHasInvalidatedResolution();
                this.resolutionCache.startCachingPerDirectoryResolution();
                this.program = this.languageService.getProgram(); // TODO: GH#18217
                this.dirty = false;
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "finishCachingPerDirectoryResolution");
                this.resolutionCache.finishCachingPerDirectoryResolution();
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
                ts.Debug.assert(oldProgram === undefined || this.program !== undefined);
                // bump up the version if
                // - oldProgram is not set - this is a first time updateGraph is called
                // - newProgram is different from the old program and structure of the old program was not reused.
                var hasNewProgram = false;
                if (this.program && (!oldProgram || (this.program !== oldProgram && this.program.structureIsReused !== 2 /* StructureIsReused.Completely */))) {
                    hasNewProgram = true;
                    if (oldProgram) {
                        for (var _i = 0, _a = oldProgram.getSourceFiles(); _i < _a.length; _i++) {
                            var f = _a[_i];
                            var newFile = this.program.getSourceFileByPath(f.resolvedPath);
                            if (!newFile || (f.resolvedPath === f.path && newFile.resolvedPath !== f.path)) {
                                // new program does not contain this file - detach it from the project
                                // - remove resolutions only if the new program doesnt contain source file by the path (not resolvedPath since path is used for resolution)
                                this.detachScriptInfoFromProject(f.fileName, !!this.program.getSourceFileByPath(f.path));
                            }
                        }
                        oldProgram.forEachResolvedProjectReference(function (resolvedProjectReference) {
                            if (!_this.program.getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) {
                                _this.detachScriptInfoFromProject(resolvedProjectReference.sourceFile.fileName);
                            }
                        });
                    }
                    // Update the missing file paths watcher
                    ts.updateMissingFilePathsWatch(this.program, this.missingFilesMap || (this.missingFilesMap = new ts.Map()), 
                    // Watch the missing files
                    function (missingFilePath) { return _this.addMissingFileWatcher(missingFilePath); });
                    if (this.generatedFilesMap) {
                        var outPath = ts.outFile(this.compilerOptions);
                        if (isGeneratedFileWatcher(this.generatedFilesMap)) {
                            // --out
                            if (!outPath || !this.isValidGeneratedFileWatcher(ts.removeFileExtension(outPath) + ".d.ts" /* Extension.Dts */, this.generatedFilesMap)) {
                                this.clearGeneratedFileWatch();
                            }
                        }
                        else {
                            // MultiFile
                            if (outPath) {
                                this.clearGeneratedFileWatch();
                            }
                            else {
                                this.generatedFilesMap.forEach(function (watcher, source) {
                                    var sourceFile = _this.program.getSourceFileByPath(source);
                                    if (!sourceFile ||
                                        sourceFile.resolvedPath !== source ||
                                        !_this.isValidGeneratedFileWatcher(ts.getDeclarationEmitOutputFilePathWorker(sourceFile.fileName, _this.compilerOptions, _this.currentDirectory, _this.program.getCommonSourceDirectory(), _this.getCanonicalFileName), watcher)) {
                                        ts.closeFileWatcherOf(watcher);
                                        _this.generatedFilesMap.delete(source);
                                    }
                                });
                            }
                        }
                    }
                    // Watch the type locations that would be added to program as part of automatic type resolutions
                    if (this.languageServiceEnabled && this.projectService.serverMode === ts.LanguageServiceMode.Semantic) {
                        this.resolutionCache.updateTypeRootsWatch();
                    }
                }
                if (this.exportMapCache && !this.exportMapCache.isEmpty()) {
                    this.exportMapCache.releaseSymbols();
                    if (this.hasAddedorRemovedFiles || oldProgram && !this.program.structureIsReused) {
                        this.exportMapCache.clear();
                    }
                    else if (this.changedFilesForExportMapCache && oldProgram && this.program) {
                        ts.forEachKey(this.changedFilesForExportMapCache, function (fileName) {
                            var oldSourceFile = oldProgram.getSourceFileByPath(fileName);
                            var sourceFile = _this.program.getSourceFileByPath(fileName);
                            if (!oldSourceFile || !sourceFile) {
                                _this.exportMapCache.clear();
                                return true;
                            }
                            return _this.exportMapCache.onFileChanged(oldSourceFile, sourceFile, !!_this.getTypeAcquisition().enable);
                        });
                    }
                }
                if (this.changedFilesForExportMapCache) {
                    this.changedFilesForExportMapCache.clear();
                }
                if (this.hasAddedOrRemovedSymlinks || this.program && !this.program.structureIsReused && this.getCompilerOptions().preserveSymlinks) {
                    // With --preserveSymlinks, we may not determine that a file is a symlink, so we never set `hasAddedOrRemovedSymlinks`
                    this.symlinks = undefined;
                    this.moduleSpecifierCache.clear();
                }
                var oldExternalFiles = this.externalFiles || server.emptyArray;
                this.externalFiles = this.getExternalFiles();
                ts.enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles, ts.getStringComparer(!this.useCaseSensitiveFileNames()), 
                // Ensure a ScriptInfo is created for new external files. This is performed indirectly
                // by the host for files in the program when the program is retrieved above but
                // the program doesn't contain external files so this must be done explicitly.
                function (inserted) {
                    var scriptInfo = _this.projectService.getOrCreateScriptInfoNotOpenedByClient(inserted, _this.currentDirectory, _this.directoryStructureHost);
                    scriptInfo === null || scriptInfo === void 0 ? void 0 : scriptInfo.attachToProject(_this);
                }, function (removed) { return _this.detachScriptInfoFromProject(removed); });
                var elapsed = ts.timestamp() - start;
                this.sendPerformanceEvent("UpdateGraph", elapsed);
                this.writeLog("Finishing updateGraphWorker: Project: ".concat(this.getProjectName(), " Version: ").concat(this.getProjectVersion(), " structureChanged: ").concat(hasNewProgram).concat(this.program ? " structureIsReused:: ".concat(ts.StructureIsReused[this.program.structureIsReused]) : "", " Elapsed: ").concat(elapsed, "ms"));
                if (this.hasAddedorRemovedFiles) {
                    this.print(/*writeProjectFileNames*/ true);
                }
                else if (this.program !== oldProgram) {
                    this.writeLog("Different program with same set of files");
                }
                return hasNewProgram;
            };
            /* @internal */
            Project.prototype.sendPerformanceEvent = function (kind, durationMs) {
                this.projectService.sendPerformanceEvent(kind, durationMs);
            };
            Project.prototype.detachScriptInfoFromProject = function (uncheckedFileName, noRemoveResolution) {
                var scriptInfoToDetach = this.projectService.getScriptInfo(uncheckedFileName);
                if (scriptInfoToDetach) {
                    scriptInfoToDetach.detachFromProject(this);
                    if (!noRemoveResolution) {
                        this.resolutionCache.removeResolutionsOfFile(scriptInfoToDetach.path);
                    }
                }
            };
            Project.prototype.addMissingFileWatcher = function (missingFilePath) {
                var _this = this;
                var _a;
                if (isConfiguredProject(this)) {
                    // If this file is referenced config file, we are already watching it, no need to watch again
                    var configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(missingFilePath);
                    if ((_a = configFileExistenceInfo === null || configFileExistenceInfo === void 0 ? void 0 : configFileExistenceInfo.config) === null || _a === void 0 ? void 0 : _a.projects.has(this.canonicalConfigFilePath))
                        return ts.noopFileWatcher;
                }
                var fileWatcher = this.projectService.watchFactory.watchFile(missingFilePath, function (fileName, eventKind) {
                    if (isConfiguredProject(_this)) {
                        _this.getCachedDirectoryStructureHost().addOrDeleteFile(fileName, missingFilePath, eventKind);
                    }
                    if (eventKind === ts.FileWatcherEventKind.Created && _this.missingFilesMap.has(missingFilePath)) {
                        _this.missingFilesMap.delete(missingFilePath);
                        fileWatcher.close();
                        // When a missing file is created, we should update the graph.
                        _this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(_this);
                    }
                }, ts.PollingInterval.Medium, this.projectService.getWatchOptions(this), ts.WatchType.MissingFile, this);
                return fileWatcher;
            };
            Project.prototype.isWatchedMissingFile = function (path) {
                return !!this.missingFilesMap && this.missingFilesMap.has(path);
            };
            /* @internal */
            Project.prototype.addGeneratedFileWatch = function (generatedFile, sourceFile) {
                if (ts.outFile(this.compilerOptions)) {
                    // Single watcher
                    if (!this.generatedFilesMap) {
                        this.generatedFilesMap = this.createGeneratedFileWatcher(generatedFile);
                    }
                }
                else {
                    // Map
                    var path = this.toPath(sourceFile);
                    if (this.generatedFilesMap) {
                        if (isGeneratedFileWatcher(this.generatedFilesMap)) {
                            ts.Debug.fail("".concat(this.projectName, " Expected to not have --out watcher for generated file with options: ").concat(JSON.stringify(this.compilerOptions)));
                            return;
                        }
                        if (this.generatedFilesMap.has(path))
                            return;
                    }
                    else {
                        this.generatedFilesMap = new ts.Map();
                    }
                    this.generatedFilesMap.set(path, this.createGeneratedFileWatcher(generatedFile));
                }
            };
            Project.prototype.createGeneratedFileWatcher = function (generatedFile) {
                var _this = this;
                return {
                    generatedFilePath: this.toPath(generatedFile),
                    watcher: this.projectService.watchFactory.watchFile(generatedFile, function () {
                        _this.clearSourceMapperCache();
                        _this.projectService.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(_this);
                    }, ts.PollingInterval.High, this.projectService.getWatchOptions(this), ts.WatchType.MissingGeneratedFile, this)
                };
            };
            Project.prototype.isValidGeneratedFileWatcher = function (generateFile, watcher) {
                return this.toPath(generateFile) === watcher.generatedFilePath;
            };
            Project.prototype.clearGeneratedFileWatch = function () {
                if (this.generatedFilesMap) {
                    if (isGeneratedFileWatcher(this.generatedFilesMap)) {
                        ts.closeFileWatcherOf(this.generatedFilesMap);
                    }
                    else {
                        ts.clearMap(this.generatedFilesMap, ts.closeFileWatcherOf);
                    }
                    this.generatedFilesMap = undefined;
                }
            };
            Project.prototype.getScriptInfoForNormalizedPath = function (fileName) {
                var scriptInfo = this.projectService.getScriptInfoForPath(this.toPath(fileName));
                if (scriptInfo && !scriptInfo.isAttached(this)) {
                    return server.Errors.ThrowProjectDoesNotContainDocument(fileName, this);
                }
                return scriptInfo;
            };
            Project.prototype.getScriptInfo = function (uncheckedFileName) {
                return this.projectService.getScriptInfo(uncheckedFileName);
            };
            Project.prototype.filesToString = function (writeProjectFileNames) {
                if (this.isInitialLoadPending())
                    return "\tFiles (0) InitialLoadPending\n";
                if (!this.program)
                    return "\tFiles (0) NoProgram\n";
                var sourceFiles = this.program.getSourceFiles();
                var strBuilder = "\tFiles (".concat(sourceFiles.length, ")\n");
                if (writeProjectFileNames) {
                    for (var _i = 0, sourceFiles_1 = sourceFiles; _i < sourceFiles_1.length; _i++) {
                        var file = sourceFiles_1[_i];
                        strBuilder += "\t".concat(file.fileName, "\n");
                    }
                    strBuilder += "\n\n";
                    ts.explainFiles(this.program, function (s) { return strBuilder += "\t".concat(s, "\n"); });
                }
                return strBuilder;
            };
            /*@internal*/
            Project.prototype.print = function (writeProjectFileNames) {
                this.writeLog("Project '".concat(this.projectName, "' (").concat(ProjectKind[this.projectKind], ")"));
                this.writeLog(this.filesToString(writeProjectFileNames && this.projectService.logger.hasLevel(server.LogLevel.verbose)));
                this.writeLog("-----------------------------------------------");
                if (this.autoImportProviderHost) {
                    this.autoImportProviderHost.print(/*writeProjectFileNames*/ false);
                }
            };
            Project.prototype.setCompilerOptions = function (compilerOptions) {
                var _a;
                if (compilerOptions) {
                    compilerOptions.allowNonTsExtensions = true;
                    var oldOptions = this.compilerOptions;
                    this.compilerOptions = compilerOptions;
                    this.setInternalCompilerOptionsForEmittingJsFiles();
                    (_a = this.noDtsResolutionProject) === null || _a === void 0 ? void 0 : _a.setCompilerOptions(this.getCompilerOptionsForNoDtsResolutionProject());
                    if (ts.changesAffectModuleResolution(oldOptions, compilerOptions)) {
                        // reset cached unresolved imports if changes in compiler options affected module resolution
                        this.cachedUnresolvedImportsPerFile.clear();
                        this.lastCachedUnresolvedImportsList = undefined;
                        this.resolutionCache.clear();
                        this.moduleSpecifierCache.clear();
                    }
                    this.markAsDirty();
                }
            };
            /*@internal*/
            Project.prototype.setWatchOptions = function (watchOptions) {
                this.watchOptions = watchOptions;
            };
            /*@internal*/
            Project.prototype.getWatchOptions = function () {
                return this.watchOptions;
            };
            Project.prototype.setTypeAcquisition = function (newTypeAcquisition) {
                if (newTypeAcquisition) {
                    this.typeAcquisition = this.removeLocalTypingsFromTypeAcquisition(newTypeAcquisition);
                }
            };
            Project.prototype.getTypeAcquisition = function () {
                return this.typeAcquisition || {};
            };
            /* @internal */
            Project.prototype.getChangesSinceVersion = function (lastKnownVersion, includeProjectReferenceRedirectInfo) {
                var _this = this;
                var includeProjectReferenceRedirectInfoIfRequested = includeProjectReferenceRedirectInfo
                    ? function (files) { return ts.arrayFrom(files.entries(), function (_a) {
                        var fileName = _a[0], isSourceOfProjectReferenceRedirect = _a[1];
                        return ({
                            fileName: fileName,
                            isSourceOfProjectReferenceRedirect: isSourceOfProjectReferenceRedirect
                        });
                    }); }
                    : function (files) { return ts.arrayFrom(files.keys()); };
                // Update the graph only if initial configured project load is not pending
                if (!this.isInitialLoadPending()) {
                    server.updateProjectIfDirty(this);
                }
                var info = {
                    projectName: this.getProjectName(),
                    version: this.projectProgramVersion,
                    isInferred: isInferredProject(this),
                    options: this.getCompilationSettings(),
                    languageServiceDisabled: !this.languageServiceEnabled,
                    lastFileExceededProgramSize: this.lastFileExceededProgramSize
                };
                var updatedFileNames = this.updatedFileNames;
                this.updatedFileNames = undefined;
                // check if requested version is the same that we have reported last time
                if (this.lastReportedFileNames && lastKnownVersion === this.lastReportedVersion) {
                    // if current structure version is the same - return info without any changes
                    if (this.projectProgramVersion === this.lastReportedVersion && !updatedFileNames) {
                        return { info: info, projectErrors: this.getGlobalProjectErrors() };
                    }
                    // compute and return the difference
                    var lastReportedFileNames_1 = this.lastReportedFileNames;
                    var externalFiles = this.getExternalFiles().map(function (f) { return ({
                        fileName: server.toNormalizedPath(f),
                        isSourceOfProjectReferenceRedirect: false
                    }); });
                    var currentFiles_1 = ts.arrayToMap(this.getFileNamesWithRedirectInfo(!!includeProjectReferenceRedirectInfo).concat(externalFiles), function (info) { return info.fileName; }, function (info) { return info.isSourceOfProjectReferenceRedirect; });
                    var added_1 = new ts.Map();
                    var removed_1 = new ts.Map();
                    var updated = updatedFileNames ? ts.arrayFrom(updatedFileNames.keys()) : [];
                    var updatedRedirects_1 = [];
                    ts.forEachEntry(currentFiles_1, function (isSourceOfProjectReferenceRedirect, fileName) {
                        if (!lastReportedFileNames_1.has(fileName)) {
                            added_1.set(fileName, isSourceOfProjectReferenceRedirect);
                        }
                        else if (includeProjectReferenceRedirectInfo && isSourceOfProjectReferenceRedirect !== lastReportedFileNames_1.get(fileName)) {
                            updatedRedirects_1.push({
                                fileName: fileName,
                                isSourceOfProjectReferenceRedirect: isSourceOfProjectReferenceRedirect
                            });
                        }
                    });
                    ts.forEachEntry(lastReportedFileNames_1, function (isSourceOfProjectReferenceRedirect, fileName) {
                        if (!currentFiles_1.has(fileName)) {
                            removed_1.set(fileName, isSourceOfProjectReferenceRedirect);
                        }
                    });
                    this.lastReportedFileNames = currentFiles_1;
                    this.lastReportedVersion = this.projectProgramVersion;
                    return {
                        info: info,
                        changes: {
                            added: includeProjectReferenceRedirectInfoIfRequested(added_1),
                            removed: includeProjectReferenceRedirectInfoIfRequested(removed_1),
                            updated: includeProjectReferenceRedirectInfo
                                ? updated.map(function (fileName) { return ({
                                    fileName: fileName,
                                    isSourceOfProjectReferenceRedirect: _this.isSourceOfProjectReferenceRedirect(fileName)
                                }); })
                                : updated,
                            updatedRedirects: includeProjectReferenceRedirectInfo ? updatedRedirects_1 : undefined
                        },
                        projectErrors: this.getGlobalProjectErrors()
                    };
                }
                else {
                    // unknown version - return everything
                    var projectFileNames = this.getFileNamesWithRedirectInfo(!!includeProjectReferenceRedirectInfo);
                    var externalFiles = this.getExternalFiles().map(function (f) { return ({
                        fileName: server.toNormalizedPath(f),
                        isSourceOfProjectReferenceRedirect: false
                    }); });
                    var allFiles = projectFileNames.concat(externalFiles);
                    this.lastReportedFileNames = ts.arrayToMap(allFiles, function (info) { return info.fileName; }, function (info) { return info.isSourceOfProjectReferenceRedirect; });
                    this.lastReportedVersion = this.projectProgramVersion;
                    return {
                        info: info,
                        files: includeProjectReferenceRedirectInfo ? allFiles : allFiles.map(function (f) { return f.fileName; }),
                        projectErrors: this.getGlobalProjectErrors()
                    };
                }
            };
            // remove a root file from project
            Project.prototype.removeRoot = function (info) {
                ts.orderedRemoveItem(this.rootFiles, info);
                this.rootFilesMap.delete(info.path);
            };
            /*@internal*/
            Project.prototype.isSourceOfProjectReferenceRedirect = function (fileName) {
                return !!this.program && this.program.isSourceOfProjectReferenceRedirect(fileName);
            };
            Project.prototype.enableGlobalPlugins = function (options, pluginConfigOverrides) {
                var host = this.projectService.host;
                if (!host.require) {
                    this.projectService.logger.info("Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded");
                    return;
                }
                // Search any globally-specified probe paths, then our peer node_modules
                var searchPaths = __spreadArray(__spreadArray([], this.projectService.pluginProbeLocations, true), [
                    // ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
                    ts.combinePaths(this.projectService.getExecutingFilePath(), "../../.."),
                ], false);
                if (this.projectService.globalPlugins) {
                    var _loop_1 = function (globalPluginName) {
                        // Skip empty names from odd commandline parses
                        if (!globalPluginName)
                            return "continue";
                        // Skip already-locally-loaded plugins
                        if (options.plugins && options.plugins.some(function (p) { return p.name === globalPluginName; }))
                            return "continue";
                        // Provide global: true so plugins can detect why they can't find their config
                        this_1.projectService.logger.info("Loading global plugin ".concat(globalPluginName));
                        this_1.enablePlugin({ name: globalPluginName, global: true }, searchPaths, pluginConfigOverrides);
                    };
                    var this_1 = this;
                    // Enable global plugins with synthetic configuration entries
                    for (var _i = 0, _a = this.projectService.globalPlugins; _i < _a.length; _i++) {
                        var globalPluginName = _a[_i];
                        _loop_1(globalPluginName);
                    }
                }
            };
            Project.prototype.enablePlugin = function (pluginConfigEntry, searchPaths, pluginConfigOverrides) {
                var _this = this;
                this.projectService.logger.info("Enabling plugin ".concat(pluginConfigEntry.name, " from candidate paths: ").concat(searchPaths.join(",")));
                if (!pluginConfigEntry.name || ts.parsePackageName(pluginConfigEntry.name).rest) {
                    this.projectService.logger.info("Skipped loading plugin ".concat(pluginConfigEntry.name || JSON.stringify(pluginConfigEntry), " because only package name is allowed plugin name"));
                    return;
                }
                var log = function (message) { return _this.projectService.logger.info(message); };
                var errorLogs;
                var logError = function (message) {
                    (errorLogs || (errorLogs = [])).push(message);
                };
                var resolvedModule = ts.firstDefined(searchPaths, function (searchPath) {
                    return Project.resolveModule(pluginConfigEntry.name, searchPath, _this.projectService.host, log, logError);
                });
                if (resolvedModule) {
                    var configurationOverride = pluginConfigOverrides && pluginConfigOverrides.get(pluginConfigEntry.name);
                    if (configurationOverride) {
                        // Preserve the name property since it's immutable
                        var pluginName = pluginConfigEntry.name;
                        pluginConfigEntry = configurationOverride;
                        pluginConfigEntry.name = pluginName;
                    }
                    this.enableProxy(resolvedModule, pluginConfigEntry);
                }
                else {
                    ts.forEach(errorLogs, log);
                    this.projectService.logger.info("Couldn't find ".concat(pluginConfigEntry.name));
                }
            };
            Project.prototype.enableProxy = function (pluginModuleFactory, configEntry) {
                try {
                    if (typeof pluginModuleFactory !== "function") {
                        this.projectService.logger.info("Skipped loading plugin ".concat(configEntry.name, " because it did not expose a proper factory function"));
                        return;
                    }
                    var info = {
                        config: configEntry,
                        project: this,
                        languageService: this.languageService,
                        languageServiceHost: this,
                        serverHost: this.projectService.host,
                        session: this.projectService.session
                    };
                    var pluginModule = pluginModuleFactory({ typescript: ts });
                    var newLS = pluginModule.create(info);
                    for (var _i = 0, _a = Object.keys(this.languageService); _i < _a.length; _i++) {
                        var k = _a[_i];
                        // eslint-disable-next-line no-in-operator
                        if (!(k in newLS)) {
                            this.projectService.logger.info("Plugin activation warning: Missing proxied method ".concat(k, " in created LS. Patching."));
                            newLS[k] = this.languageService[k];
                        }
                    }
                    this.projectService.logger.info("Plugin validation succeeded");
                    this.languageService = newLS;
                    this.plugins.push({ name: configEntry.name, module: pluginModule });
                }
                catch (e) {
                    this.projectService.logger.info("Plugin activation failed: ".concat(e));
                }
            };
            /*@internal*/
            Project.prototype.onPluginConfigurationChanged = function (pluginName, configuration) {
                this.plugins.filter(function (plugin) { return plugin.name === pluginName; }).forEach(function (plugin) {
                    if (plugin.module.onConfigurationChanged) {
                        plugin.module.onConfigurationChanged(configuration);
                    }
                });
            };
            /** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */
            Project.prototype.refreshDiagnostics = function () {
                this.projectService.sendProjectsUpdatedInBackgroundEvent();
            };
            /*@internal*/
            Project.prototype.getPackageJsonsVisibleToFile = function (fileName, rootDir) {
                if (this.projectService.serverMode !== ts.LanguageServiceMode.Semantic)
                    return server.emptyArray;
                return this.projectService.getPackageJsonsVisibleToFile(fileName, rootDir);
            };
            /*@internal*/
            Project.prototype.getNearestAncestorDirectoryWithPackageJson = function (fileName) {
                return this.projectService.getNearestAncestorDirectoryWithPackageJson(fileName);
            };
            /*@internal*/
            Project.prototype.getPackageJsonsForAutoImport = function (rootDir) {
                var packageJsons = this.getPackageJsonsVisibleToFile(ts.combinePaths(this.currentDirectory, ts.inferredTypesContainingFile), rootDir);
                this.packageJsonsForAutoImport = new ts.Set(packageJsons.map(function (p) { return p.fileName; }));
                return packageJsons;
            };
            /* @internal */
            Project.prototype.getPackageJsonCache = function () {
                return this.projectService.packageJsonCache;
            };
            /*@internal*/
            Project.prototype.getCachedExportInfoMap = function () {
                return this.exportMapCache || (this.exportMapCache = ts.createCacheableExportInfoMap(this));
            };
            /*@internal*/
            Project.prototype.clearCachedExportInfoMap = function () {
                var _a;
                (_a = this.exportMapCache) === null || _a === void 0 ? void 0 : _a.clear();
            };
            /*@internal*/
            Project.prototype.getModuleSpecifierCache = function () {
                return this.moduleSpecifierCache;
            };
            /*@internal*/
            Project.prototype.includePackageJsonAutoImports = function () {
                if (this.projectService.includePackageJsonAutoImports() === 0 /* PackageJsonAutoImportPreference.Off */ ||
                    !this.languageServiceEnabled ||
                    ts.isInsideNodeModules(this.currentDirectory) ||
                    !this.isDefaultProjectForOpenFiles()) {
                    return 0 /* PackageJsonAutoImportPreference.Off */;
                }
                return this.projectService.includePackageJsonAutoImports();
            };
            /*@internal*/
            Project.prototype.getModuleResolutionHostForAutoImportProvider = function () {
                var _a, _b;
                if (this.program) {
                    return {
                        fileExists: this.program.fileExists,
                        directoryExists: this.program.directoryExists,
                        realpath: this.program.realpath || ((_a = this.projectService.host.realpath) === null || _a === void 0 ? void 0 : _a.bind(this.projectService.host)),
                        getCurrentDirectory: this.getCurrentDirectory.bind(this),
                        readFile: this.projectService.host.readFile.bind(this.projectService.host),
                        getDirectories: this.projectService.host.getDirectories.bind(this.projectService.host),
                        trace: (_b = this.projectService.host.trace) === null || _b === void 0 ? void 0 : _b.bind(this.projectService.host),
                        useCaseSensitiveFileNames: this.program.useCaseSensitiveFileNames(),
                    };
                }
                return this.projectService.host;
            };
            /*@internal*/
            Project.prototype.getPackageJsonAutoImportProvider = function () {
                if (this.autoImportProviderHost === false) {
                    return undefined;
                }
                if (this.projectService.serverMode !== ts.LanguageServiceMode.Semantic) {
                    this.autoImportProviderHost = false;
                    return undefined;
                }
                if (this.autoImportProviderHost) {
                    server.updateProjectIfDirty(this.autoImportProviderHost);
                    if (this.autoImportProviderHost.isEmpty()) {
                        this.autoImportProviderHost.close();
                        this.autoImportProviderHost = undefined;
                        return undefined;
                    }
                    return this.autoImportProviderHost.getCurrentProgram();
                }
                var dependencySelection = this.includePackageJsonAutoImports();
                if (dependencySelection) {
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "getPackageJsonAutoImportProvider");
                    var start = ts.timestamp();
                    this.autoImportProviderHost = AutoImportProviderProject.create(dependencySelection, this, this.getModuleResolutionHostForAutoImportProvider(), this.documentRegistry);
                    if (this.autoImportProviderHost) {
                        server.updateProjectIfDirty(this.autoImportProviderHost);
                        this.sendPerformanceEvent("CreatePackageJsonAutoImportProvider", ts.timestamp() - start);
                        ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
                        return this.autoImportProviderHost.getCurrentProgram();
                    }
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
                }
            };
            /*@internal*/
            Project.prototype.isDefaultProjectForOpenFiles = function () {
                var _this = this;
                return !!ts.forEachEntry(this.projectService.openFiles, function (_, fileName) { return _this.projectService.tryGetDefaultProjectForFile(server.toNormalizedPath(fileName)) === _this; });
            };
            /*@internal*/
            Project.prototype.watchNodeModulesForPackageJsonChanges = function (directoryPath) {
                return this.projectService.watchPackageJsonsInNodeModules(this.toPath(directoryPath), this);
            };
            /*@internal*/
            Project.prototype.getIncompleteCompletionsCache = function () {
                return this.projectService.getIncompleteCompletionsCache();
            };
            /*@internal*/
            Project.prototype.getNoDtsResolutionProject = function (rootFileNames) {
                var _this = this;
                ts.Debug.assert(this.projectService.serverMode === ts.LanguageServiceMode.Semantic);
                if (!this.noDtsResolutionProject) {
                    this.noDtsResolutionProject = new AuxiliaryProject(this.projectService, this.documentRegistry, this.getCompilerOptionsForNoDtsResolutionProject());
                }
                ts.enumerateInsertsAndDeletes(rootFileNames.map(server.toNormalizedPath), this.noDtsResolutionProject.getRootFiles(), ts.getStringComparer(!this.useCaseSensitiveFileNames()), function (pathToAdd) {
                    var info = _this.projectService.getOrCreateScriptInfoNotOpenedByClient(pathToAdd, _this.currentDirectory, _this.noDtsResolutionProject.directoryStructureHost);
                    if (info) {
                        _this.noDtsResolutionProject.addRoot(info, pathToAdd);
                    }
                }, function (pathToRemove) {
                    // It may be preferable to remove roots only once project grows to a certain size?
                    var info = _this.noDtsResolutionProject.getScriptInfo(pathToRemove);
                    if (info) {
                        _this.noDtsResolutionProject.removeRoot(info);
                    }
                });
                return this.noDtsResolutionProject;
            };
            /*@internal*/
            Project.prototype.getCompilerOptionsForNoDtsResolutionProject = function () {
                return __assign(__assign({}, this.getCompilerOptions()), { noDtsResolution: true, allowJs: true, maxNodeModuleJsDepth: 3, diagnostics: false, skipLibCheck: true, sourceMap: false, types: ts.emptyArray, lib: ts.emptyArray, noLib: true });
            };
            return Project;
        }());
        server.Project = Project;
        function getUnresolvedImports(program, cachedUnresolvedImportsPerFile) {
            var sourceFiles = program.getSourceFiles();
            ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "getUnresolvedImports", { count: sourceFiles.length });
            var ambientModules = program.getTypeChecker().getAmbientModules().map(function (mod) { return ts.stripQuotes(mod.getName()); });
            var result = ts.sortAndDeduplicate(ts.flatMap(sourceFiles, function (sourceFile) {
                return extractUnresolvedImportsFromSourceFile(sourceFile, ambientModules, cachedUnresolvedImportsPerFile);
            }));
            ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
            return result;
        }
        function extractUnresolvedImportsFromSourceFile(file, ambientModules, cachedUnresolvedImportsPerFile) {
            return ts.getOrUpdate(cachedUnresolvedImportsPerFile, file.path, function () {
                if (!file.resolvedModules)
                    return server.emptyArray;
                var unresolvedImports;
                file.resolvedModules.forEach(function (resolvedModule, name) {
                    // pick unresolved non-relative names
                    if ((!resolvedModule || !ts.resolutionExtensionIsTSOrJson(resolvedModule.extension)) &&
                        !ts.isExternalModuleNameRelative(name) &&
                        !ambientModules.some(function (m) { return m === name; })) {
                        unresolvedImports = ts.append(unresolvedImports, ts.parsePackageName(name).packageName);
                    }
                });
                return unresolvedImports || server.emptyArray;
            });
        }
        /**
         * If a file is opened and no tsconfig (or jsconfig) is found,
         * the file and its imports/references are put into an InferredProject.
         */
        var InferredProject = /** @class */ (function (_super) {
            __extends(InferredProject, _super);
            /*@internal*/
            function InferredProject(projectService, documentRegistry, compilerOptions, watchOptions, projectRootPath, currentDirectory, pluginConfigOverrides, typeAcquisition) {
                var _this = _super.call(this, projectService.newInferredProjectName(), ProjectKind.Inferred, projectService, documentRegistry, 
                // TODO: GH#18217
                /*files*/ undefined, 
                /*lastFileExceededProgramSize*/ undefined, compilerOptions, 
                /*compileOnSaveEnabled*/ false, watchOptions, projectService.host, currentDirectory) || this;
                _this._isJsInferredProject = false;
                _this.typeAcquisition = typeAcquisition;
                _this.projectRootPath = projectRootPath && projectService.toCanonicalFileName(projectRootPath);
                if (!projectRootPath && !projectService.useSingleInferredProject) {
                    _this.canonicalCurrentDirectory = projectService.toCanonicalFileName(_this.currentDirectory);
                }
                _this.enableGlobalPlugins(_this.getCompilerOptions(), pluginConfigOverrides);
                return _this;
            }
            InferredProject.prototype.toggleJsInferredProject = function (isJsInferredProject) {
                if (isJsInferredProject !== this._isJsInferredProject) {
                    this._isJsInferredProject = isJsInferredProject;
                    this.setCompilerOptions();
                }
            };
            InferredProject.prototype.setCompilerOptions = function (options) {
                // Avoid manipulating the given options directly
                if (!options && !this.getCompilationSettings()) {
                    return;
                }
                var newOptions = ts.cloneCompilerOptions(options || this.getCompilationSettings());
                if (this._isJsInferredProject && typeof newOptions.maxNodeModuleJsDepth !== "number") {
                    newOptions.maxNodeModuleJsDepth = 2;
                }
                else if (!this._isJsInferredProject) {
                    newOptions.maxNodeModuleJsDepth = undefined;
                }
                newOptions.allowJs = true;
                _super.prototype.setCompilerOptions.call(this, newOptions);
            };
            InferredProject.prototype.addRoot = function (info) {
                ts.Debug.assert(info.isScriptOpen());
                this.projectService.startWatchingConfigFilesForInferredProjectRoot(info);
                if (!this._isJsInferredProject && info.isJavaScript()) {
                    this.toggleJsInferredProject(/*isJsInferredProject*/ true);
                }
                _super.prototype.addRoot.call(this, info);
            };
            InferredProject.prototype.removeRoot = function (info) {
                this.projectService.stopWatchingConfigFilesForInferredProjectRoot(info);
                _super.prototype.removeRoot.call(this, info);
                if (this._isJsInferredProject && info.isJavaScript()) {
                    if (ts.every(this.getRootScriptInfos(), function (rootInfo) { return !rootInfo.isJavaScript(); })) {
                        this.toggleJsInferredProject(/*isJsInferredProject*/ false);
                    }
                }
            };
            /*@internal*/
            InferredProject.prototype.isOrphan = function () {
                return !this.hasRoots();
            };
            InferredProject.prototype.isProjectWithSingleRoot = function () {
                // - when useSingleInferredProject is not set and projectRootPath is not set,
                //   we can guarantee that this will be the only root
                // - other wise it has single root if it has single root script info
                return (!this.projectRootPath && !this.projectService.useSingleInferredProject) ||
                    this.getRootScriptInfos().length === 1;
            };
            InferredProject.prototype.close = function () {
                var _this = this;
                ts.forEach(this.getRootScriptInfos(), function (info) { return _this.projectService.stopWatchingConfigFilesForInferredProjectRoot(info); });
                _super.prototype.close.call(this);
            };
            InferredProject.prototype.getTypeAcquisition = function () {
                return this.typeAcquisition || {
                    enable: allRootFilesAreJsOrDts(this),
                    include: ts.emptyArray,
                    exclude: ts.emptyArray
                };
            };
            return InferredProject;
        }(Project));
        server.InferredProject = InferredProject;
        var AuxiliaryProject = /** @class */ (function (_super) {
            __extends(AuxiliaryProject, _super);
            function AuxiliaryProject(projectService, documentRegistry, compilerOptions) {
                return _super.call(this, projectService.newAuxiliaryProjectName(), ProjectKind.Auxiliary, projectService, documentRegistry, 
                /*hasExplicitListOfFiles*/ false, 
                /*lastFileExceededProgramSize*/ undefined, compilerOptions, 
                /*compileOnSaveEnabled*/ false, 
                /*watchOptions*/ undefined, projectService.host, 
                /*currentDirectory*/ undefined) || this;
            }
            AuxiliaryProject.prototype.isOrphan = function () {
                return true;
            };
            /*@internal*/
            AuxiliaryProject.prototype.scheduleInvalidateResolutionsOfFailedLookupLocations = function () {
                // Invalidation will happen on-demand as part of updateGraph
                return;
            };
            return AuxiliaryProject;
        }(Project));
        var AutoImportProviderProject = /** @class */ (function (_super) {
            __extends(AutoImportProviderProject, _super);
            /*@internal*/
            function AutoImportProviderProject(hostProject, initialRootNames, documentRegistry, compilerOptions) {
                var _this = _super.call(this, hostProject.projectService.newAutoImportProviderProjectName(), ProjectKind.AutoImportProvider, hostProject.projectService, documentRegistry, 
                /*hasExplicitListOfFiles*/ false, 
                /*lastFileExceededProgramSize*/ undefined, compilerOptions, 
                /*compileOnSaveEnabled*/ false, hostProject.getWatchOptions(), hostProject.projectService.host, hostProject.currentDirectory) || this;
                _this.hostProject = hostProject;
                _this.rootFileNames = initialRootNames;
                _this.useSourceOfProjectReferenceRedirect = ts.maybeBind(_this.hostProject, _this.hostProject.useSourceOfProjectReferenceRedirect);
                _this.getParsedCommandLine = ts.maybeBind(_this.hostProject, _this.hostProject.getParsedCommandLine);
                return _this;
            }
            /*@internal*/
            AutoImportProviderProject.getRootFileNames = function (dependencySelection, hostProject, moduleResolutionHost, compilerOptions) {
                var _a, _b;
                if (!dependencySelection) {
                    return ts.emptyArray;
                }
                var program = hostProject.getCurrentProgram();
                if (!program) {
                    return ts.emptyArray;
                }
                var start = ts.timestamp();
                var dependencyNames;
                var rootNames;
                var rootFileName = ts.combinePaths(hostProject.currentDirectory, ts.inferredTypesContainingFile);
                var packageJsons = hostProject.getPackageJsonsForAutoImport(ts.combinePaths(hostProject.currentDirectory, rootFileName));
                for (var _i = 0, packageJsons_1 = packageJsons; _i < packageJsons_1.length; _i++) {
                    var packageJson = packageJsons_1[_i];
                    (_a = packageJson.dependencies) === null || _a === void 0 ? void 0 : _a.forEach(function (_, dependenyName) { return addDependency(dependenyName); });
                    (_b = packageJson.peerDependencies) === null || _b === void 0 ? void 0 : _b.forEach(function (_, dependencyName) { return addDependency(dependencyName); });
                }
                var dependenciesAdded = 0;
                if (dependencyNames) {
                    var symlinkCache_1 = hostProject.getSymlinkCache();
                    var _loop_2 = function (name) {
                        // Avoid creating a large project that would significantly slow down time to editor interactivity
                        if (dependencySelection === 2 /* PackageJsonAutoImportPreference.Auto */ && dependenciesAdded > this_2.maxDependencies) {
                            hostProject.log("AutoImportProviderProject: attempted to add more than ".concat(this_2.maxDependencies, " dependencies. Aborting."));
                            return { value: ts.emptyArray };
                        }
                        // 1. Try to load from the implementation package. For many dependencies, the
                        //    package.json will exist, but the package will not contain any typings,
                        //    so `entrypoints` will be undefined. In that case, or if the dependency
                        //    is missing altogether, we will move on to trying the @types package (2).
                        var packageJson = ts.resolvePackageNameToPackageJson(name, hostProject.currentDirectory, compilerOptions, moduleResolutionHost, program.getModuleResolutionCache());
                        if (packageJson) {
                            var entrypoints = getRootNamesFromPackageJson(packageJson, program, symlinkCache_1);
                            if (entrypoints) {
                                rootNames = ts.concatenate(rootNames, entrypoints);
                                dependenciesAdded += entrypoints.length ? 1 : 0;
                                return "continue";
                            }
                        }
                        // 2. Try to load from the @types package in the tree and in the global
                        //    typings cache location, if enabled.
                        var done = ts.forEach([hostProject.currentDirectory, hostProject.getGlobalTypingsCacheLocation()], function (directory) {
                            if (directory) {
                                var typesPackageJson = ts.resolvePackageNameToPackageJson("@types/".concat(name), directory, compilerOptions, moduleResolutionHost, program.getModuleResolutionCache());
                                if (typesPackageJson) {
                                    var entrypoints = getRootNamesFromPackageJson(typesPackageJson, program, symlinkCache_1);
                                    rootNames = ts.concatenate(rootNames, entrypoints);
                                    dependenciesAdded += (entrypoints === null || entrypoints === void 0 ? void 0 : entrypoints.length) ? 1 : 0;
                                    return true;
                                }
                            }
                        });
                        if (done)
                            return "continue";
                        // 3. If the @types package did not exist and the user has settings that
                        //    allow processing JS from node_modules, go back to the implementation
                        //    package and load the JS.
                        if (packageJson && compilerOptions.allowJs && compilerOptions.maxNodeModuleJsDepth) {
                            var entrypoints = getRootNamesFromPackageJson(packageJson, program, symlinkCache_1, /*allowJs*/ true);
                            rootNames = ts.concatenate(rootNames, entrypoints);
                            dependenciesAdded += (entrypoints === null || entrypoints === void 0 ? void 0 : entrypoints.length) ? 1 : 0;
                        }
                    };
                    var this_2 = this;
                    for (var _c = 0, _d = ts.arrayFrom(dependencyNames.keys()); _c < _d.length; _c++) {
                        var name = _d[_c];
                        var state_1 = _loop_2(name);
                        if (typeof state_1 === "object")
                            return state_1.value;
                    }
                }
                if (rootNames === null || rootNames === void 0 ? void 0 : rootNames.length) {
                    hostProject.log("AutoImportProviderProject: found ".concat(rootNames.length, " root files in ").concat(dependenciesAdded, " dependencies in ").concat(ts.timestamp() - start, " ms"));
                }
                return rootNames || ts.emptyArray;
                function addDependency(dependency) {
                    if (!ts.startsWith(dependency, "@types/")) {
                        (dependencyNames || (dependencyNames = new ts.Set())).add(dependency);
                    }
                }
                function getRootNamesFromPackageJson(packageJson, program, symlinkCache, resolveJs) {
                    var _a;
                    var entrypoints = ts.getEntrypointsFromPackageJsonInfo(packageJson, compilerOptions, moduleResolutionHost, program.getModuleResolutionCache(), resolveJs);
                    if (entrypoints) {
                        var real_1 = (_a = moduleResolutionHost.realpath) === null || _a === void 0 ? void 0 : _a.call(moduleResolutionHost, packageJson.packageDirectory);
                        var isSymlink_1 = real_1 && real_1 !== packageJson.packageDirectory;
                        if (isSymlink_1) {
                            symlinkCache.setSymlinkedDirectory(packageJson.packageDirectory, {
                                real: real_1,
                                realPath: hostProject.toPath(real_1),
                            });
                        }
                        return ts.mapDefined(entrypoints, function (entrypoint) {
                            var resolvedFileName = isSymlink_1 ? entrypoint.replace(packageJson.packageDirectory, real_1) : entrypoint;
                            if (!program.getSourceFile(resolvedFileName) && !(isSymlink_1 && program.getSourceFile(entrypoint))) {
                                return resolvedFileName;
                            }
                        });
                    }
                }
            };
            /*@internal*/
            AutoImportProviderProject.create = function (dependencySelection, hostProject, moduleResolutionHost, documentRegistry) {
                if (dependencySelection === 0 /* PackageJsonAutoImportPreference.Off */) {
                    return undefined;
                }
                var compilerOptions = __assign(__assign({}, hostProject.getCompilerOptions()), this.compilerOptionsOverrides);
                var rootNames = this.getRootFileNames(dependencySelection, hostProject, moduleResolutionHost, compilerOptions);
                if (!rootNames.length) {
                    return undefined;
                }
                return new AutoImportProviderProject(hostProject, rootNames, documentRegistry, compilerOptions);
            };
            /*@internal*/
            AutoImportProviderProject.prototype.isEmpty = function () {
                return !ts.some(this.rootFileNames);
            };
            AutoImportProviderProject.prototype.isOrphan = function () {
                return true;
            };
            AutoImportProviderProject.prototype.updateGraph = function () {
                var rootFileNames = this.rootFileNames;
                if (!rootFileNames) {
                    rootFileNames = AutoImportProviderProject.getRootFileNames(this.hostProject.includePackageJsonAutoImports(), this.hostProject, this.hostProject.getModuleResolutionHostForAutoImportProvider(), this.getCompilationSettings());
                }
                this.projectService.setFileNamesOfAutoImportProviderProject(this, rootFileNames);
                this.rootFileNames = rootFileNames;
                var oldProgram = this.getCurrentProgram();
                var hasSameSetOfFiles = _super.prototype.updateGraph.call(this);
                if (oldProgram && oldProgram !== this.getCurrentProgram()) {
                    this.hostProject.clearCachedExportInfoMap();
                }
                return hasSameSetOfFiles;
            };
            /*@internal*/
            AutoImportProviderProject.prototype.scheduleInvalidateResolutionsOfFailedLookupLocations = function () {
                // Invalidation will happen on-demand as part of updateGraph
                return;
            };
            AutoImportProviderProject.prototype.hasRoots = function () {
                var _a;
                return !!((_a = this.rootFileNames) === null || _a === void 0 ? void 0 : _a.length);
            };
            AutoImportProviderProject.prototype.markAsDirty = function () {
                this.rootFileNames = undefined;
                _super.prototype.markAsDirty.call(this);
            };
            AutoImportProviderProject.prototype.getScriptFileNames = function () {
                return this.rootFileNames || ts.emptyArray;
            };
            AutoImportProviderProject.prototype.getLanguageService = function () {
                throw new Error("AutoImportProviderProject language service should never be used. To get the program, use `project.getCurrentProgram()`.");
            };
            /*@internal*/
            AutoImportProviderProject.prototype.onAutoImportProviderSettingsChanged = function () {
                throw new Error("AutoImportProviderProject is an auto import provider; use `markAsDirty()` instead.");
            };
            /*@internal*/
            AutoImportProviderProject.prototype.onPackageJsonChange = function () {
                throw new Error("package.json changes should be notified on an AutoImportProvider's host project");
            };
            AutoImportProviderProject.prototype.getModuleResolutionHostForAutoImportProvider = function () {
                throw new Error("AutoImportProviderProject cannot provide its own host; use `hostProject.getModuleResolutionHostForAutomImportProvider()` instead.");
            };
            AutoImportProviderProject.prototype.getProjectReferences = function () {
                return this.hostProject.getProjectReferences();
            };
            /*@internal*/
            AutoImportProviderProject.prototype.includePackageJsonAutoImports = function () {
                return 0 /* PackageJsonAutoImportPreference.Off */;
            };
            AutoImportProviderProject.prototype.getTypeAcquisition = function () {
                return { enable: false };
            };
            /*@internal*/
            AutoImportProviderProject.prototype.getSymlinkCache = function () {
                return this.hostProject.getSymlinkCache();
            };
            /*@internal*/
            AutoImportProviderProject.prototype.getModuleResolutionCache = function () {
                var _a;
                return (_a = this.hostProject.getCurrentProgram()) === null || _a === void 0 ? void 0 : _a.getModuleResolutionCache();
            };
            /*@internal*/
            AutoImportProviderProject.maxDependencies = 10;
            /*@internal*/
            AutoImportProviderProject.compilerOptionsOverrides = {
                diagnostics: false,
                skipLibCheck: true,
                sourceMap: false,
                types: ts.emptyArray,
                lib: ts.emptyArray,
                noLib: true,
            };
            return AutoImportProviderProject;
        }(Project));
        server.AutoImportProviderProject = AutoImportProviderProject;
        /**
         * If a file is opened, the server will look for a tsconfig (or jsconfig)
         * and if successful create a ConfiguredProject for it.
         * Otherwise it will create an InferredProject.
         */
        var ConfiguredProject = /** @class */ (function (_super) {
            __extends(ConfiguredProject, _super);
            /*@internal*/
            function ConfiguredProject(configFileName, canonicalConfigFilePath, projectService, documentRegistry, cachedDirectoryStructureHost) {
                var _this = _super.call(this, configFileName, ProjectKind.Configured, projectService, documentRegistry, 
                /*hasExplicitListOfFiles*/ false, 
                /*lastFileExceededProgramSize*/ undefined, 
                /*compilerOptions*/ {}, 
                /*compileOnSaveEnabled*/ false, 
                /*watchOptions*/ undefined, cachedDirectoryStructureHost, ts.getDirectoryPath(configFileName)) || this;
                _this.canonicalConfigFilePath = canonicalConfigFilePath;
                /* @internal */
                _this.openFileWatchTriggered = new ts.Map();
                /*@internal*/
                _this.canConfigFileJsonReportNoInputFiles = false;
                /** Ref count to the project when opened from external project */
                _this.externalProjectRefCount = 0;
                /*@internal*/
                _this.isInitialLoadPending = ts.returnTrue;
                /*@internal*/
                _this.sendLoadingProjectFinish = false;
                return _this;
            }
            /* @internal */
            ConfiguredProject.prototype.setCompilerHost = function (host) {
                this.compilerHost = host;
            };
            /* @internal */
            ConfiguredProject.prototype.getCompilerHost = function () {
                return this.compilerHost;
            };
            /* @internal */
            ConfiguredProject.prototype.useSourceOfProjectReferenceRedirect = function () {
                return this.languageServiceEnabled;
            };
            /* @internal */
            ConfiguredProject.prototype.getParsedCommandLine = function (fileName) {
                var configFileName = server.asNormalizedPath(ts.normalizePath(fileName));
                var canonicalConfigFilePath = server.asNormalizedPath(this.projectService.toCanonicalFileName(configFileName));
                // Ensure the config file existience info is cached
                var configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                if (!configFileExistenceInfo) {
                    this.projectService.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo = { exists: this.projectService.host.fileExists(configFileName) });
                }
                // Ensure we have upto date parsed command line
                this.projectService.ensureParsedConfigUptoDate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, this);
                // Watch wild cards if LS is enabled
                if (this.languageServiceEnabled && this.projectService.serverMode === ts.LanguageServiceMode.Semantic) {
                    this.projectService.watchWildcards(configFileName, configFileExistenceInfo, this);
                }
                return configFileExistenceInfo.exists ? configFileExistenceInfo.config.parsedCommandLine : undefined;
            };
            /* @internal */
            ConfiguredProject.prototype.onReleaseParsedCommandLine = function (fileName) {
                this.releaseParsedConfig(server.asNormalizedPath(this.projectService.toCanonicalFileName(server.asNormalizedPath(ts.normalizePath(fileName)))));
            };
            /* @internal */
            ConfiguredProject.prototype.releaseParsedConfig = function (canonicalConfigFilePath) {
                this.projectService.stopWatchingWildCards(canonicalConfigFilePath, this);
                this.projectService.releaseParsedConfig(canonicalConfigFilePath, this);
            };
            /**
             * If the project has reload from disk pending, it reloads (and then updates graph as part of that) instead of just updating the graph
             * @returns: true if set of files in the project stays the same and false - otherwise.
             */
            ConfiguredProject.prototype.updateGraph = function () {
                var isInitialLoad = this.isInitialLoadPending();
                this.isInitialLoadPending = ts.returnFalse;
                var reloadLevel = this.pendingReload;
                this.pendingReload = ts.ConfigFileProgramReloadLevel.None;
                var result;
                switch (reloadLevel) {
                    case ts.ConfigFileProgramReloadLevel.Partial:
                        this.openFileWatchTriggered.clear();
                        result = this.projectService.reloadFileNamesOfConfiguredProject(this);
                        break;
                    case ts.ConfigFileProgramReloadLevel.Full:
                        this.openFileWatchTriggered.clear();
                        var reason = ts.Debug.checkDefined(this.pendingReloadReason);
                        this.pendingReloadReason = undefined;
                        this.projectService.reloadConfiguredProject(this, reason, isInitialLoad, /*clearSemanticCache*/ false);
                        result = true;
                        break;
                    default:
                        result = _super.prototype.updateGraph.call(this);
                }
                this.compilerHost = undefined;
                this.projectService.sendProjectLoadingFinishEvent(this);
                this.projectService.sendProjectTelemetry(this);
                return result;
            };
            /*@internal*/
            ConfiguredProject.prototype.getCachedDirectoryStructureHost = function () {
                return this.directoryStructureHost;
            };
            ConfiguredProject.prototype.getConfigFilePath = function () {
                return server.asNormalizedPath(this.getProjectName());
            };
            ConfiguredProject.prototype.getProjectReferences = function () {
                return this.projectReferences;
            };
            ConfiguredProject.prototype.updateReferences = function (refs) {
                this.projectReferences = refs;
                this.potentialProjectReferences = undefined;
            };
            /*@internal*/
            ConfiguredProject.prototype.setPotentialProjectReference = function (canonicalConfigPath) {
                ts.Debug.assert(this.isInitialLoadPending());
                (this.potentialProjectReferences || (this.potentialProjectReferences = new ts.Set())).add(canonicalConfigPath);
            };
            /*@internal*/
            ConfiguredProject.prototype.getResolvedProjectReferenceToRedirect = function (fileName) {
                var program = this.getCurrentProgram();
                return program && program.getResolvedProjectReferenceToRedirect(fileName);
            };
            /*@internal*/
            ConfiguredProject.prototype.forEachResolvedProjectReference = function (cb) {
                var _a;
                return (_a = this.getCurrentProgram()) === null || _a === void 0 ? void 0 : _a.forEachResolvedProjectReference(cb);
            };
            /*@internal*/
            ConfiguredProject.prototype.enablePluginsWithOptions = function (options, pluginConfigOverrides) {
                var host = this.projectService.host;
                if (!host.require) {
                    this.projectService.logger.info("Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded");
                    return;
                }
                // Search our peer node_modules, then any globally-specified probe paths
                // ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
                var searchPaths = __spreadArray([ts.combinePaths(this.projectService.getExecutingFilePath(), "../../..")], this.projectService.pluginProbeLocations, true);
                if (this.projectService.allowLocalPluginLoads) {
                    var local = ts.getDirectoryPath(this.canonicalConfigFilePath);
                    this.projectService.logger.info("Local plugin loading enabled; adding ".concat(local, " to search paths"));
                    searchPaths.unshift(local);
                }
                // Enable tsconfig-specified plugins
                if (options.plugins) {
                    for (var _i = 0, _a = options.plugins; _i < _a.length; _i++) {
                        var pluginConfigEntry = _a[_i];
                        this.enablePlugin(pluginConfigEntry, searchPaths, pluginConfigOverrides);
                    }
                }
                this.enableGlobalPlugins(options, pluginConfigOverrides);
            };
            /**
             * Get the errors that dont have any file name associated
             */
            ConfiguredProject.prototype.getGlobalProjectErrors = function () {
                return ts.filter(this.projectErrors, function (diagnostic) { return !diagnostic.file; }) || server.emptyArray;
            };
            /**
             * Get all the project errors
             */
            ConfiguredProject.prototype.getAllProjectErrors = function () {
                return this.projectErrors || server.emptyArray;
            };
            ConfiguredProject.prototype.setProjectErrors = function (projectErrors) {
                this.projectErrors = projectErrors;
            };
            ConfiguredProject.prototype.close = function () {
                var _this = this;
                this.projectService.configFileExistenceInfoCache.forEach(function (_configFileExistenceInfo, canonicalConfigFilePath) {
                    return _this.releaseParsedConfig(canonicalConfigFilePath);
                });
                this.projectErrors = undefined;
                this.openFileWatchTriggered.clear();
                this.compilerHost = undefined;
                _super.prototype.close.call(this);
            };
            /* @internal */
            ConfiguredProject.prototype.addExternalProjectReference = function () {
                this.externalProjectRefCount++;
            };
            /* @internal */
            ConfiguredProject.prototype.deleteExternalProjectReference = function () {
                this.externalProjectRefCount--;
            };
            /* @internal */
            ConfiguredProject.prototype.isSolution = function () {
                return this.getRootFilesMap().size === 0 &&
                    !this.canConfigFileJsonReportNoInputFiles;
            };
            /* @internal */
            /** Find the configured project from the project references in project which contains the info directly */
            ConfiguredProject.prototype.getDefaultChildProjectFromProjectWithReferences = function (info) {
                return server.forEachResolvedProjectReferenceProject(this, info.path, function (child) { return server.projectContainsInfoDirectly(child, info) ?
                    child :
                    undefined; }, server.ProjectReferenceProjectLoadKind.Find);
            };
            /** Returns true if the project is needed by any of the open script info/external project */
            /* @internal */
            ConfiguredProject.prototype.hasOpenRef = function () {
                var _this = this;
                var _a;
                if (!!this.externalProjectRefCount) {
                    return true;
                }
                // Closed project doesnt have any reference
                if (this.isClosed()) {
                    return false;
                }
                var configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(this.canonicalConfigFilePath);
                if (this.projectService.hasPendingProjectUpdate(this)) {
                    // If there is pending update for this project,
                    // we dont know if this project would be needed by any of the open files impacted by this config file
                    // In that case keep the project alive if there are open files impacted by this project
                    return !!((_a = configFileExistenceInfo.openFilesImpactedByConfigFile) === null || _a === void 0 ? void 0 : _a.size);
                }
                // If there is no pending update for this project,
                // We know exact set of open files that get impacted by this configured project as the files in the project
                // The project is referenced only if open files impacted by this project are present in this project
                return !!configFileExistenceInfo.openFilesImpactedByConfigFile && ts.forEachEntry(configFileExistenceInfo.openFilesImpactedByConfigFile, function (_value, infoPath) {
                    var info = _this.projectService.getScriptInfoForPath(infoPath);
                    return _this.containsScriptInfo(info) ||
                        !!server.forEachResolvedProjectReferenceProject(_this, info.path, function (child) { return child.containsScriptInfo(info); }, server.ProjectReferenceProjectLoadKind.Find);
                }) || false;
            };
            /*@internal*/
            ConfiguredProject.prototype.hasExternalProjectRef = function () {
                return !!this.externalProjectRefCount;
            };
            ConfiguredProject.prototype.getEffectiveTypeRoots = function () {
                return ts.getEffectiveTypeRoots(this.getCompilationSettings(), this.directoryStructureHost) || [];
            };
            /*@internal*/
            ConfiguredProject.prototype.updateErrorOnNoInputFiles = function (fileNames) {
                ts.updateErrorForNoInputFiles(fileNames, this.getConfigFilePath(), this.getCompilerOptions().configFile.configFileSpecs, this.projectErrors, this.canConfigFileJsonReportNoInputFiles);
            };
            return ConfiguredProject;
        }(Project));
        server.ConfiguredProject = ConfiguredProject;
        /**
         * Project whose configuration is handled externally, such as in a '.csproj'.
         * These are created only if a host explicitly calls `openExternalProject`.
         */
        var ExternalProject = /** @class */ (function (_super) {
            __extends(ExternalProject, _super);
            /*@internal*/
            function ExternalProject(externalProjectName, projectService, documentRegistry, compilerOptions, lastFileExceededProgramSize, compileOnSaveEnabled, projectFilePath, pluginConfigOverrides, watchOptions) {
                var _this = _super.call(this, externalProjectName, ProjectKind.External, projectService, documentRegistry, 
                /*hasExplicitListOfFiles*/ true, lastFileExceededProgramSize, compilerOptions, compileOnSaveEnabled, watchOptions, projectService.host, ts.getDirectoryPath(projectFilePath || ts.normalizeSlashes(externalProjectName))) || this;
                _this.externalProjectName = externalProjectName;
                _this.compileOnSaveEnabled = compileOnSaveEnabled;
                _this.excludedFiles = [];
                _this.enableGlobalPlugins(_this.getCompilerOptions(), pluginConfigOverrides);
                return _this;
            }
            ExternalProject.prototype.updateGraph = function () {
                var result = _super.prototype.updateGraph.call(this);
                this.projectService.sendProjectTelemetry(this);
                return result;
            };
            ExternalProject.prototype.getExcludedFiles = function () {
                return this.excludedFiles;
            };
            return ExternalProject;
        }(Project));
        server.ExternalProject = ExternalProject;
        /* @internal */
        function isInferredProject(project) {
            return project.projectKind === ProjectKind.Inferred;
        }
        server.isInferredProject = isInferredProject;
        /* @internal */
        function isConfiguredProject(project) {
            return project.projectKind === ProjectKind.Configured;
        }
        server.isConfiguredProject = isConfiguredProject;
        /* @internal */
        function isExternalProject(project) {
            return project.projectKind === ProjectKind.External;
        }
        server.isExternalProject = isExternalProject;
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
var ts;
(function (ts) {
    var server;
    (function (server) {
        server.maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
        /*@internal*/
        server.maxFileSize = 4 * 1024 * 1024;
        server.ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground";
        server.ProjectLoadingStartEvent = "projectLoadingStart";
        server.ProjectLoadingFinishEvent = "projectLoadingFinish";
        server.LargeFileReferencedEvent = "largeFileReferenced";
        server.ConfigFileDiagEvent = "configFileDiag";
        server.ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
        server.ProjectInfoTelemetryEvent = "projectInfo";
        server.OpenFileInfoTelemetryEvent = "openFileInfo";
        var ensureProjectForOpenFileSchedule = "*ensureProjectForOpenFiles*";
        function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions) {
            var map = new ts.Map();
            for (var _i = 0, commandLineOptions_1 = commandLineOptions; _i < commandLineOptions_1.length; _i++) {
                var option = commandLineOptions_1[_i];
                if (typeof option.type === "object") {
                    var optionMap = option.type;
                    // verify that map contains only numbers
                    optionMap.forEach(function (value) {
                        ts.Debug.assert(typeof value === "number");
                    });
                    map.set(option.name, optionMap);
                }
            }
            return map;
        }
        var compilerOptionConverters = prepareConvertersForEnumLikeCompilerOptions(ts.optionDeclarations);
        var watchOptionsConverters = prepareConvertersForEnumLikeCompilerOptions(ts.optionsForWatch);
        var indentStyle = new ts.Map(ts.getEntries({
            none: ts.IndentStyle.None,
            block: ts.IndentStyle.Block,
            smart: ts.IndentStyle.Smart
        }));
        /**
         * How to understand this block:
         *  * The 'match' property is a regexp that matches a filename.
         *  * If 'match' is successful, then:
         *     * All files from 'exclude' are removed from the project. See below.
         *     * All 'types' are included in ATA
         *  * What the heck is 'exclude' ?
         *     * An array of an array of strings and numbers
         *     * Each array is:
         *       * An array of strings and numbers
         *       * The strings are literals
         *       * The numbers refer to capture group indices from the 'match' regexp
         *          * Remember that '1' is the first group
         *       * These are concatenated together to form a new regexp
         *       * Filenames matching these regexps are excluded from the project
         * This default value is tested in tsserverProjectSystem.ts; add tests there
         *   if you are changing this so that you can be sure your regexp works!
         */
        var defaultTypeSafeList = {
            "jquery": {
                // jquery files can have names like "jquery-1.10.2.min.js" (or "jquery.intellisense.js")
                match: /jquery(-[\d\.]+)?(\.intellisense)?(\.min)?\.js$/i,
                types: ["jquery"]
            },
            "WinJS": {
                // e.g. c:/temp/UWApp1/lib/winjs-4.0.1/js/base.js
                match: /^(.*\/winjs-[.\d]+)\/js\/base\.js$/i,
                exclude: [["^", 1, "/.*"]],
                types: ["winjs"] // And fetch the @types package for WinJS
            },
            "Kendo": {
                // e.g. /Kendo3/wwwroot/lib/kendo/kendo.all.min.js
                match: /^(.*\/kendo(-ui)?)\/kendo\.all(\.min)?\.js$/i,
                exclude: [["^", 1, "/.*"]],
                types: ["kendo-ui"]
            },
            "Office Nuget": {
                // e.g. /scripts/Office/1/excel-15.debug.js
                match: /^(.*\/office\/1)\/excel-\d+\.debug\.js$/i,
                exclude: [["^", 1, "/.*"]],
                types: ["office"] // @types package to fetch instead
            },
            "References": {
                match: /^(.*\/_references\.js)$/i,
                exclude: [["^", 1, "$"]]
            }
        };
        function convertFormatOptions(protocolOptions) {
            if (ts.isString(protocolOptions.indentStyle)) {
                protocolOptions.indentStyle = indentStyle.get(protocolOptions.indentStyle.toLowerCase());
                ts.Debug.assert(protocolOptions.indentStyle !== undefined);
            }
            return protocolOptions;
        }
        server.convertFormatOptions = convertFormatOptions;
        function convertCompilerOptions(protocolOptions) {
            compilerOptionConverters.forEach(function (mappedValues, id) {
                var propertyValue = protocolOptions[id];
                if (ts.isString(propertyValue)) {
                    protocolOptions[id] = mappedValues.get(propertyValue.toLowerCase());
                }
            });
            return protocolOptions;
        }
        server.convertCompilerOptions = convertCompilerOptions;
        function convertWatchOptions(protocolOptions, currentDirectory) {
            var watchOptions;
            var errors;
            ts.optionsForWatch.forEach(function (option) {
                var propertyValue = protocolOptions[option.name];
                if (propertyValue === undefined)
                    return;
                var mappedValues = watchOptionsConverters.get(option.name);
                (watchOptions || (watchOptions = {}))[option.name] = mappedValues ?
                    ts.isString(propertyValue) ? mappedValues.get(propertyValue.toLowerCase()) : propertyValue :
                    ts.convertJsonOption(option, propertyValue, currentDirectory || "", errors || (errors = []));
            });
            return watchOptions && { watchOptions: watchOptions, errors: errors };
        }
        server.convertWatchOptions = convertWatchOptions;
        function convertTypeAcquisition(protocolOptions) {
            var result;
            ts.typeAcquisitionDeclarations.forEach(function (option) {
                var propertyValue = protocolOptions[option.name];
                if (propertyValue === undefined)
                    return;
                (result || (result = {}))[option.name] = propertyValue;
            });
            return result;
        }
        server.convertTypeAcquisition = convertTypeAcquisition;
        function tryConvertScriptKindName(scriptKindName) {
            return ts.isString(scriptKindName) ? convertScriptKindName(scriptKindName) : scriptKindName;
        }
        server.tryConvertScriptKindName = tryConvertScriptKindName;
        function convertScriptKindName(scriptKindName) {
            switch (scriptKindName) {
                case "JS":
                    return 1 /* ScriptKind.JS */;
                case "JSX":
                    return 2 /* ScriptKind.JSX */;
                case "TS":
                    return 3 /* ScriptKind.TS */;
                case "TSX":
                    return 4 /* ScriptKind.TSX */;
                default:
                    return 0 /* ScriptKind.Unknown */;
            }
        }
        server.convertScriptKindName = convertScriptKindName;
        /*@internal*/
        function convertUserPreferences(preferences) {
            var lazyConfiguredProjectsFromExternalProject = preferences.lazyConfiguredProjectsFromExternalProject, userPreferences = __rest(preferences, ["lazyConfiguredProjectsFromExternalProject"]);
            return userPreferences;
        }
        server.convertUserPreferences = convertUserPreferences;
        var fileNamePropertyReader = {
            getFileName: function (x) { return x; },
            getScriptKind: function (fileName, extraFileExtensions) {
                var result;
                if (extraFileExtensions) {
                    var fileExtension_1 = ts.getAnyExtensionFromPath(fileName);
                    if (fileExtension_1) {
                        ts.some(extraFileExtensions, function (info) {
                            if (info.extension === fileExtension_1) {
                                result = info.scriptKind;
                                return true;
                            }
                            return false;
                        });
                    }
                }
                return result; // TODO: GH#18217
            },
            hasMixedContent: function (fileName, extraFileExtensions) { return ts.some(extraFileExtensions, function (ext) { return ext.isMixedContent && ts.fileExtensionIs(fileName, ext.extension); }); },
        };
        var externalFilePropertyReader = {
            getFileName: function (x) { return x.fileName; },
            getScriptKind: function (x) { return tryConvertScriptKindName(x.scriptKind); },
            hasMixedContent: function (x) { return !!x.hasMixedContent; },
        };
        function findProjectByName(projectName, projects) {
            for (var _i = 0, projects_1 = projects; _i < projects_1.length; _i++) {
                var proj = projects_1[_i];
                if (proj.getProjectName() === projectName) {
                    return proj;
                }
            }
        }
        var noopConfigFileWatcher = { close: ts.noop };
        function isOpenScriptInfo(infoOrFileNameOrConfig) {
            return !!infoOrFileNameOrConfig.containingProjects;
        }
        function isAncestorConfigFileInfo(infoOrFileNameOrConfig) {
            return !!infoOrFileNameOrConfig.configFileInfo;
        }
        /*@internal*/
        /** Kind of operation to perform to get project reference project */
        var ProjectReferenceProjectLoadKind;
        (function (ProjectReferenceProjectLoadKind) {
            /** Find existing project for project reference */
            ProjectReferenceProjectLoadKind[ProjectReferenceProjectLoadKind["Find"] = 0] = "Find";
            /** Find existing project or create one for the project reference */
            ProjectReferenceProjectLoadKind[ProjectReferenceProjectLoadKind["FindCreate"] = 1] = "FindCreate";
            /** Find existing project or create and load it for the project reference */
            ProjectReferenceProjectLoadKind[ProjectReferenceProjectLoadKind["FindCreateLoad"] = 2] = "FindCreateLoad";
        })(ProjectReferenceProjectLoadKind = server.ProjectReferenceProjectLoadKind || (server.ProjectReferenceProjectLoadKind = {}));
        function forEachResolvedProjectReferenceProject(project, fileName, cb, projectReferenceProjectLoadKind, reason) {
            var _a;
            var resolvedRefs = (_a = project.getCurrentProgram()) === null || _a === void 0 ? void 0 : _a.getResolvedProjectReferences();
            if (!resolvedRefs)
                return undefined;
            var seenResolvedRefs;
            var possibleDefaultRef = fileName ? project.getResolvedProjectReferenceToRedirect(fileName) : undefined;
            if (possibleDefaultRef) {
                // Try to find the name of the file directly through resolved project references
                var configFileName = server.toNormalizedPath(possibleDefaultRef.sourceFile.fileName);
                var child = project.projectService.findConfiguredProjectByProjectName(configFileName);
                if (child) {
                    var result = cb(child);
                    if (result)
                        return result;
                }
                else if (projectReferenceProjectLoadKind !== ProjectReferenceProjectLoadKind.Find) {
                    seenResolvedRefs = new ts.Map();
                    // Try to see if this project can be loaded
                    var result = forEachResolvedProjectReferenceProjectWorker(resolvedRefs, project.getCompilerOptions(), function (ref, loadKind) { return possibleDefaultRef === ref ? callback(ref, loadKind) : undefined; }, projectReferenceProjectLoadKind, project.projectService, seenResolvedRefs);
                    if (result)
                        return result;
                    // Cleanup seenResolvedRefs
                    seenResolvedRefs.clear();
                }
            }
            return forEachResolvedProjectReferenceProjectWorker(resolvedRefs, project.getCompilerOptions(), function (ref, loadKind) { return possibleDefaultRef !== ref ? callback(ref, loadKind) : undefined; }, projectReferenceProjectLoadKind, project.projectService, seenResolvedRefs);
            function callback(ref, loadKind) {
                var configFileName = server.toNormalizedPath(ref.sourceFile.fileName);
                var child = project.projectService.findConfiguredProjectByProjectName(configFileName) || (loadKind === ProjectReferenceProjectLoadKind.Find ?
                    undefined :
                    loadKind === ProjectReferenceProjectLoadKind.FindCreate ?
                        project.projectService.createConfiguredProject(configFileName) :
                        loadKind === ProjectReferenceProjectLoadKind.FindCreateLoad ?
                            project.projectService.createAndLoadConfiguredProject(configFileName, reason) :
                            ts.Debug.assertNever(loadKind));
                return child && cb(child);
            }
        }
        server.forEachResolvedProjectReferenceProject = forEachResolvedProjectReferenceProject;
        function forEachResolvedProjectReferenceProjectWorker(resolvedProjectReferences, parentOptions, cb, projectReferenceProjectLoadKind, projectService, seenResolvedRefs) {
            var loadKind = parentOptions.disableReferencedProjectLoad ? ProjectReferenceProjectLoadKind.Find : projectReferenceProjectLoadKind;
            return ts.forEach(resolvedProjectReferences, function (ref) {
                if (!ref)
                    return undefined;
                var configFileName = server.toNormalizedPath(ref.sourceFile.fileName);
                var canonicalPath = projectService.toCanonicalFileName(configFileName);
                var seenValue = seenResolvedRefs === null || seenResolvedRefs === void 0 ? void 0 : seenResolvedRefs.get(canonicalPath);
                if (seenValue !== undefined && seenValue >= loadKind) {
                    return undefined;
                }
                var result = cb(ref, loadKind);
                if (result) {
                    return result;
                }
                (seenResolvedRefs || (seenResolvedRefs = new ts.Map())).set(canonicalPath, loadKind);
                return ref.references && forEachResolvedProjectReferenceProjectWorker(ref.references, ref.commandLine.options, cb, loadKind, projectService, seenResolvedRefs);
            });
        }
        function forEachPotentialProjectReference(project, cb) {
            return project.potentialProjectReferences &&
                ts.forEachKey(project.potentialProjectReferences, cb);
        }
        function forEachAnyProjectReferenceKind(project, cb, cbProjectRef, cbPotentialProjectRef) {
            return project.getCurrentProgram() ?
                project.forEachResolvedProjectReference(cb) :
                project.isInitialLoadPending() ?
                    forEachPotentialProjectReference(project, cbPotentialProjectRef) :
                    ts.forEach(project.getProjectReferences(), cbProjectRef);
        }
        function callbackRefProject(project, cb, refPath) {
            var refProject = refPath && project.projectService.configuredProjects.get(refPath);
            return refProject && cb(refProject);
        }
        function forEachReferencedProject(project, cb) {
            return forEachAnyProjectReferenceKind(project, function (resolvedRef) { return callbackRefProject(project, cb, resolvedRef.sourceFile.path); }, function (projectRef) { return callbackRefProject(project, cb, project.toPath(ts.resolveProjectReferencePath(projectRef))); }, function (potentialProjectRef) { return callbackRefProject(project, cb, potentialProjectRef); });
        }
        function getDetailWatchInfo(watchType, project) {
            return "".concat(ts.isString(project) ? "Config: ".concat(project, " ") : project ? "Project: ".concat(project.getProjectName(), " ") : "", "WatchType: ").concat(watchType);
        }
        function isScriptInfoWatchedFromNodeModules(info) {
            return !info.isScriptOpen() && info.mTime !== undefined;
        }
        /*@internal*/
        /** true if script info is part of project and is not in project because it is referenced from project reference source */
        function projectContainsInfoDirectly(project, info) {
            return project.containsScriptInfo(info) &&
                !project.isSourceOfProjectReferenceRedirect(info.path);
        }
        server.projectContainsInfoDirectly = projectContainsInfoDirectly;
        /*@internal*/
        function updateProjectIfDirty(project) {
            project.invalidateResolutionsOfFailedLookupLocations();
            return project.dirty && project.updateGraph();
        }
        server.updateProjectIfDirty = updateProjectIfDirty;
        function setProjectOptionsUsed(project) {
            if (server.isConfiguredProject(project)) {
                project.projectOptions = true;
            }
        }
        function createProjectNameFactoryWithCounter(nameFactory) {
            var nextId = 1;
            return function () { return nameFactory(nextId++); };
        }
        var ProjectService = /** @class */ (function () {
            function ProjectService(opts) {
                var _this = this;
                /**
                 * Container of all known scripts
                 */
                /*@internal*/
                this.filenameToScriptInfo = new ts.Map();
                this.nodeModulesWatchers = new ts.Map();
                /**
                 * Contains all the deleted script info's version information so that
                 * it does not reset when creating script info again
                 * (and could have potentially collided with version where contents mismatch)
                 */
                this.filenameToScriptInfoVersion = new ts.Map();
                // Set of all '.js' files ever opened.
                this.allJsFilesForOpenFileTelemetry = new ts.Map();
                /**
                 * maps external project file name to list of config files that were the part of this project
                 */
                this.externalProjectToConfiguredProjectMap = new ts.Map();
                /**
                 * external projects (configuration and list of root files is not controlled by tsserver)
                 */
                this.externalProjects = [];
                /**
                 * projects built from openFileRoots
                 */
                this.inferredProjects = [];
                /**
                 * projects specified by a tsconfig.json file
                 */
                this.configuredProjects = new ts.Map();
                /*@internal*/
                this.newInferredProjectName = createProjectNameFactoryWithCounter(server.makeInferredProjectName);
                /*@internal*/
                this.newAutoImportProviderProjectName = createProjectNameFactoryWithCounter(server.makeAutoImportProviderProjectName);
                /*@internal*/
                this.newAuxiliaryProjectName = createProjectNameFactoryWithCounter(server.makeAuxiliaryProjectName);
                /**
                 * Open files: with value being project root path, and key being Path of the file that is open
                 */
                this.openFiles = new ts.Map();
                /* @internal */
                this.configFileForOpenFiles = new ts.Map();
                /**
                 * Map of open files that are opened without complete path but have projectRoot as current directory
                 */
                this.openFilesWithNonRootedDiskPath = new ts.Map();
                this.compilerOptionsForInferredProjectsPerProjectRoot = new ts.Map();
                this.watchOptionsForInferredProjectsPerProjectRoot = new ts.Map();
                this.typeAcquisitionForInferredProjectsPerProjectRoot = new ts.Map();
                /**
                 * Project size for configured or external projects
                 */
                this.projectToSizeMap = new ts.Map();
                /**
                 * This is a map of config file paths existence that doesnt need query to disk
                 * - The entry can be present because there is inferred project that needs to watch addition of config file to directory
                 *   In this case the exists could be true/false based on config file is present or not
                 * - Or it is present if we have configured project open with config file at that location
                 *   In this case the exists property is always true
                 */
                /*@internal*/ this.configFileExistenceInfoCache = new ts.Map();
                this.safelist = defaultTypeSafeList;
                this.legacySafelist = new ts.Map();
                this.pendingProjectUpdates = new ts.Map();
                /* @internal */
                this.pendingEnsureProjectForOpenFiles = false;
                /** Tracks projects that we have already sent telemetry for. */
                this.seenProjects = new ts.Map();
                /*@internal*/
                this.sharedExtendedConfigFileWatchers = new ts.Map();
                /*@internal*/
                this.extendedConfigCache = new ts.Map();
                this.host = opts.host;
                this.logger = opts.logger;
                this.cancellationToken = opts.cancellationToken;
                this.useSingleInferredProject = opts.useSingleInferredProject;
                this.useInferredProjectPerProjectRoot = opts.useInferredProjectPerProjectRoot;
                this.typingsInstaller = opts.typingsInstaller || server.nullTypingsInstaller;
                this.throttleWaitMilliseconds = opts.throttleWaitMilliseconds;
                this.eventHandler = opts.eventHandler;
                this.suppressDiagnosticEvents = opts.suppressDiagnosticEvents;
                this.globalPlugins = opts.globalPlugins || server.emptyArray;
                this.pluginProbeLocations = opts.pluginProbeLocations || server.emptyArray;
                this.allowLocalPluginLoads = !!opts.allowLocalPluginLoads;
                this.typesMapLocation = (opts.typesMapLocation === undefined) ? ts.combinePaths(ts.getDirectoryPath(this.getExecutingFilePath()), "typesMap.json") : opts.typesMapLocation;
                this.session = opts.session;
                if (opts.serverMode !== undefined) {
                    this.serverMode = opts.serverMode;
                    this.syntaxOnly = this.serverMode === ts.LanguageServiceMode.Syntactic;
                }
                else if (opts.syntaxOnly) {
                    this.serverMode = ts.LanguageServiceMode.Syntactic;
                    this.syntaxOnly = true;
                }
                else {
                    this.serverMode = ts.LanguageServiceMode.Semantic;
                    this.syntaxOnly = false;
                }
                if (this.host.realpath) {
                    this.realpathToScriptInfos = ts.createMultiMap();
                }
                this.currentDirectory = server.toNormalizedPath(this.host.getCurrentDirectory());
                this.toCanonicalFileName = ts.createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
                this.globalCacheLocationDirectoryPath = this.typingsInstaller.globalTypingsCacheLocation
                    ? ts.ensureTrailingDirectorySeparator(this.toPath(this.typingsInstaller.globalTypingsCacheLocation))
                    : undefined;
                this.throttledOperations = new server.ThrottledOperations(this.host, this.logger);
                if (this.typesMapLocation) {
                    this.loadTypesMap();
                }
                else {
                    this.logger.info("No types map provided; using the default");
                }
                this.typingsInstaller.attach(this);
                this.typingsCache = new server.TypingsCache(this.typingsInstaller);
                this.hostConfiguration = {
                    formatCodeOptions: ts.getDefaultFormatCodeSettings(this.host.newLine),
                    preferences: ts.emptyOptions,
                    hostInfo: "Unknown host",
                    extraFileExtensions: [],
                };
                this.documentRegistry = ts.createDocumentRegistryInternal(this.host.useCaseSensitiveFileNames, this.currentDirectory, this);
                var watchLogLevel = this.logger.hasLevel(server.LogLevel.verbose) ? ts.WatchLogLevel.Verbose :
                    this.logger.loggingEnabled() ? ts.WatchLogLevel.TriggerOnly : ts.WatchLogLevel.None;
                var log = watchLogLevel !== ts.WatchLogLevel.None ? (function (s) { return _this.logger.info(s); }) : ts.noop;
                this.packageJsonCache = server.createPackageJsonCache(this);
                this.watchFactory = this.serverMode !== ts.LanguageServiceMode.Semantic ?
                    {
                        watchFile: ts.returnNoopFileWatcher,
                        watchDirectory: ts.returnNoopFileWatcher,
                    } :
                    ts.getWatchFactory(this.host, watchLogLevel, log, getDetailWatchInfo);
            }
            ProjectService.prototype.toPath = function (fileName) {
                return ts.toPath(fileName, this.currentDirectory, this.toCanonicalFileName);
            };
            /*@internal*/
            ProjectService.prototype.getExecutingFilePath = function () {
                return this.getNormalizedAbsolutePath(this.host.getExecutingFilePath());
            };
            /*@internal*/
            ProjectService.prototype.getNormalizedAbsolutePath = function (fileName) {
                return ts.getNormalizedAbsolutePath(fileName, this.host.getCurrentDirectory());
            };
            /*@internal*/
            ProjectService.prototype.setDocument = function (key, path, sourceFile) {
                var info = ts.Debug.checkDefined(this.getScriptInfoForPath(path));
                info.cacheSourceFile = { key: key, sourceFile: sourceFile };
            };
            /*@internal*/
            ProjectService.prototype.getDocument = function (key, path) {
                var info = this.getScriptInfoForPath(path);
                return info && info.cacheSourceFile && info.cacheSourceFile.key === key ? info.cacheSourceFile.sourceFile : undefined;
            };
            /* @internal */
            ProjectService.prototype.ensureInferredProjectsUpToDate_TestOnly = function () {
                this.ensureProjectStructuresUptoDate();
            };
            /* @internal */
            ProjectService.prototype.getCompilerOptionsForInferredProjects = function () {
                return this.compilerOptionsForInferredProjects;
            };
            /* @internal */
            ProjectService.prototype.onUpdateLanguageServiceStateForProject = function (project, languageServiceEnabled) {
                if (!this.eventHandler) {
                    return;
                }
                var event = {
                    eventName: server.ProjectLanguageServiceStateEvent,
                    data: { project: project, languageServiceEnabled: languageServiceEnabled }
                };
                this.eventHandler(event);
            };
            ProjectService.prototype.loadTypesMap = function () {
                try {
                    var fileContent = this.host.readFile(this.typesMapLocation); // TODO: GH#18217
                    if (fileContent === undefined) {
                        this.logger.info("Provided types map file \"".concat(this.typesMapLocation, "\" doesn't exist"));
                        return;
                    }
                    var raw = JSON.parse(fileContent);
                    // Parse the regexps
                    for (var _i = 0, _a = Object.keys(raw.typesMap); _i < _a.length; _i++) {
                        var k = _a[_i];
                        raw.typesMap[k].match = new RegExp(raw.typesMap[k].match, "i");
                    }
                    // raw is now fixed and ready
                    this.safelist = raw.typesMap;
                    for (var key in raw.simpleMap) {
                        if (raw.simpleMap.hasOwnProperty(key)) {
                            this.legacySafelist.set(key, raw.simpleMap[key].toLowerCase());
                        }
                    }
                }
                catch (e) {
                    this.logger.info("Error loading types map: ".concat(e));
                    this.safelist = defaultTypeSafeList;
                    this.legacySafelist.clear();
                }
            };
            ProjectService.prototype.updateTypingsForProject = function (response) {
                var project = this.findProject(response.projectName);
                if (!project) {
                    return;
                }
                switch (response.kind) {
                    case server.ActionSet:
                        // Update the typing files and update the project
                        project.updateTypingFiles(this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typeAcquisition, response.unresolvedImports, response.typings));
                        return;
                    case server.ActionInvalidate:
                        // Do not clear resolution cache, there was changes detected in typings, so enque typing request and let it get us correct results
                        this.typingsCache.enqueueInstallTypingsForProject(project, project.lastCachedUnresolvedImportsList, /*forceRefresh*/ true);
                        return;
                }
            };
            /*@internal*/
            ProjectService.prototype.delayEnsureProjectForOpenFiles = function () {
                var _this = this;
                if (!this.openFiles.size)
                    return;
                this.pendingEnsureProjectForOpenFiles = true;
                this.throttledOperations.schedule(ensureProjectForOpenFileSchedule, /*delay*/ 2500, function () {
                    if (_this.pendingProjectUpdates.size !== 0) {
                        _this.delayEnsureProjectForOpenFiles();
                    }
                    else {
                        if (_this.pendingEnsureProjectForOpenFiles) {
                            _this.ensureProjectForOpenFiles();
                            // Send the event to notify that there were background project updates
                            // send current list of open files
                            _this.sendProjectsUpdatedInBackgroundEvent();
                        }
                    }
                });
            };
            ProjectService.prototype.delayUpdateProjectGraph = function (project) {
                var _this = this;
                project.markAsDirty();
                if (project.projectKind !== server.ProjectKind.AutoImportProvider && project.projectKind !== server.ProjectKind.Auxiliary) {
                    var projectName_1 = project.getProjectName();
                    this.pendingProjectUpdates.set(projectName_1, project);
                    this.throttledOperations.schedule(projectName_1, /*delay*/ 250, function () {
                        if (_this.pendingProjectUpdates.delete(projectName_1)) {
                            updateProjectIfDirty(project);
                        }
                    });
                }
            };
            /*@internal*/
            ProjectService.prototype.hasPendingProjectUpdate = function (project) {
                return this.pendingProjectUpdates.has(project.getProjectName());
            };
            /* @internal */
            ProjectService.prototype.sendProjectsUpdatedInBackgroundEvent = function () {
                var _this = this;
                if (!this.eventHandler) {
                    return;
                }
                var event = {
                    eventName: server.ProjectsUpdatedInBackgroundEvent,
                    data: {
                        openFiles: ts.arrayFrom(this.openFiles.keys(), function (path) { return _this.getScriptInfoForPath(path).fileName; })
                    }
                };
                this.eventHandler(event);
            };
            /* @internal */
            ProjectService.prototype.sendLargeFileReferencedEvent = function (file, fileSize) {
                if (!this.eventHandler) {
                    return;
                }
                var event = {
                    eventName: server.LargeFileReferencedEvent,
                    data: { file: file, fileSize: fileSize, maxFileSize: server.maxFileSize }
                };
                this.eventHandler(event);
            };
            /* @internal */
            ProjectService.prototype.sendProjectLoadingStartEvent = function (project, reason) {
                if (!this.eventHandler) {
                    return;
                }
                project.sendLoadingProjectFinish = true;
                var event = {
                    eventName: server.ProjectLoadingStartEvent,
                    data: { project: project, reason: reason }
                };
                this.eventHandler(event);
            };
            /* @internal */
            ProjectService.prototype.sendProjectLoadingFinishEvent = function (project) {
                if (!this.eventHandler || !project.sendLoadingProjectFinish) {
                    return;
                }
                project.sendLoadingProjectFinish = false;
                var event = {
                    eventName: server.ProjectLoadingFinishEvent,
                    data: { project: project }
                };
                this.eventHandler(event);
            };
            /* @internal */
            ProjectService.prototype.sendPerformanceEvent = function (kind, durationMs) {
                if (this.performanceEventHandler) {
                    this.performanceEventHandler({ kind: kind, durationMs: durationMs });
                }
            };
            /* @internal */
            ProjectService.prototype.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles = function (project) {
                this.delayUpdateProjectGraph(project);
                this.delayEnsureProjectForOpenFiles();
            };
            ProjectService.prototype.delayUpdateProjectGraphs = function (projects, clearSourceMapperCache) {
                if (projects.length) {
                    for (var _i = 0, projects_2 = projects; _i < projects_2.length; _i++) {
                        var project = projects_2[_i];
                        // Even if program doesnt change, clear the source mapper cache
                        if (clearSourceMapperCache)
                            project.clearSourceMapperCache();
                        this.delayUpdateProjectGraph(project);
                    }
                    this.delayEnsureProjectForOpenFiles();
                }
            };
            ProjectService.prototype.setCompilerOptionsForInferredProjects = function (projectCompilerOptions, projectRootPath) {
                ts.Debug.assert(projectRootPath === undefined || this.useInferredProjectPerProjectRoot, "Setting compiler options per project root path is only supported when useInferredProjectPerProjectRoot is enabled");
                var compilerOptions = convertCompilerOptions(projectCompilerOptions);
                var watchOptions = convertWatchOptions(projectCompilerOptions, projectRootPath);
                var typeAcquisition = convertTypeAcquisition(projectCompilerOptions);
                // always set 'allowNonTsExtensions' for inferred projects since user cannot configure it from the outside
                // previously we did not expose a way for user to change these settings and this option was enabled by default
                compilerOptions.allowNonTsExtensions = true;
                var canonicalProjectRootPath = projectRootPath && this.toCanonicalFileName(projectRootPath);
                if (canonicalProjectRootPath) {
                    this.compilerOptionsForInferredProjectsPerProjectRoot.set(canonicalProjectRootPath, compilerOptions);
                    this.watchOptionsForInferredProjectsPerProjectRoot.set(canonicalProjectRootPath, watchOptions || false);
                    this.typeAcquisitionForInferredProjectsPerProjectRoot.set(canonicalProjectRootPath, typeAcquisition);
                }
                else {
                    this.compilerOptionsForInferredProjects = compilerOptions;
                    this.watchOptionsForInferredProjects = watchOptions;
                    this.typeAcquisitionForInferredProjects = typeAcquisition;
                }
                for (var _i = 0, _a = this.inferredProjects; _i < _a.length; _i++) {
                    var project = _a[_i];
                    // Only update compiler options in the following cases:
                    // - Inferred projects without a projectRootPath, if the new options do not apply to
                    //   a workspace root
                    // - Inferred projects with a projectRootPath, if the new options do not apply to a
                    //   workspace root and there is no more specific set of options for that project's
                    //   root path
                    // - Inferred projects with a projectRootPath, if the new options apply to that
                    //   project root path.
                    if (canonicalProjectRootPath ?
                        project.projectRootPath === canonicalProjectRootPath :
                        !project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)) {
                        project.setCompilerOptions(compilerOptions);
                        project.setTypeAcquisition(typeAcquisition);
                        project.setWatchOptions(watchOptions === null || watchOptions === void 0 ? void 0 : watchOptions.watchOptions);
                        project.setProjectErrors(watchOptions === null || watchOptions === void 0 ? void 0 : watchOptions.errors);
                        project.compileOnSaveEnabled = compilerOptions.compileOnSave;
                        project.markAsDirty();
                        this.delayUpdateProjectGraph(project);
                    }
                }
                this.delayEnsureProjectForOpenFiles();
            };
            ProjectService.prototype.findProject = function (projectName) {
                if (projectName === undefined) {
                    return undefined;
                }
                if (server.isInferredProjectName(projectName)) {
                    return findProjectByName(projectName, this.inferredProjects);
                }
                return this.findExternalProjectByProjectName(projectName) || this.findConfiguredProjectByProjectName(server.toNormalizedPath(projectName));
            };
            /* @internal */
            ProjectService.prototype.forEachProject = function (cb) {
                this.externalProjects.forEach(cb);
                this.configuredProjects.forEach(cb);
                this.inferredProjects.forEach(cb);
            };
            /* @internal */
            ProjectService.prototype.forEachEnabledProject = function (cb) {
                this.forEachProject(function (project) {
                    if (!project.isOrphan() && project.languageServiceEnabled) {
                        cb(project);
                    }
                });
            };
            ProjectService.prototype.getDefaultProjectForFile = function (fileName, ensureProject) {
                return ensureProject ? this.ensureDefaultProjectForFile(fileName) : this.tryGetDefaultProjectForFile(fileName);
            };
            /* @internal */
            ProjectService.prototype.tryGetDefaultProjectForFile = function (fileName) {
                var scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
                return scriptInfo && !scriptInfo.isOrphan() ? scriptInfo.getDefaultProject() : undefined;
            };
            /* @internal */
            ProjectService.prototype.ensureDefaultProjectForFile = function (fileName) {
                return this.tryGetDefaultProjectForFile(fileName) || this.doEnsureDefaultProjectForFile(fileName);
            };
            ProjectService.prototype.doEnsureDefaultProjectForFile = function (fileName) {
                this.ensureProjectStructuresUptoDate();
                var scriptInfo = this.getScriptInfoForNormalizedPath(fileName);
                return scriptInfo ? scriptInfo.getDefaultProject() : (this.logErrorForScriptInfoNotFound(fileName), server.Errors.ThrowNoProject());
            };
            ProjectService.prototype.getScriptInfoEnsuringProjectsUptoDate = function (uncheckedFileName) {
                this.ensureProjectStructuresUptoDate();
                return this.getScriptInfo(uncheckedFileName);
            };
            /**
             * Ensures the project structures are upto date
             * This means,
             * - we go through all the projects and update them if they are dirty
             * - if updates reflect some change in structure or there was pending request to ensure projects for open files
             *   ensure that each open script info has project
             */
            ProjectService.prototype.ensureProjectStructuresUptoDate = function () {
                var hasChanges = this.pendingEnsureProjectForOpenFiles;
                this.pendingProjectUpdates.clear();
                var updateGraph = function (project) {
                    hasChanges = updateProjectIfDirty(project) || hasChanges;
                };
                this.externalProjects.forEach(updateGraph);
                this.configuredProjects.forEach(updateGraph);
                this.inferredProjects.forEach(updateGraph);
                if (hasChanges) {
                    this.ensureProjectForOpenFiles();
                }
            };
            ProjectService.prototype.getFormatCodeOptions = function (file) {
                var info = this.getScriptInfoForNormalizedPath(file);
                return info && info.getFormatCodeSettings() || this.hostConfiguration.formatCodeOptions;
            };
            ProjectService.prototype.getPreferences = function (file) {
                var info = this.getScriptInfoForNormalizedPath(file);
                return __assign(__assign({}, this.hostConfiguration.preferences), info && info.getPreferences());
            };
            ProjectService.prototype.getHostFormatCodeOptions = function () {
                return this.hostConfiguration.formatCodeOptions;
            };
            ProjectService.prototype.getHostPreferences = function () {
                return this.hostConfiguration.preferences;
            };
            ProjectService.prototype.onSourceFileChanged = function (info, eventKind) {
                if (eventKind === ts.FileWatcherEventKind.Deleted) {
                    // File was deleted
                    this.handleDeletedFile(info);
                }
                else if (!info.isScriptOpen()) {
                    // file has been changed which might affect the set of referenced files in projects that include
                    // this file and set of inferred projects
                    info.delayReloadNonMixedContentFile();
                    this.delayUpdateProjectGraphs(info.containingProjects, /*clearSourceMapperCache*/ false);
                    this.handleSourceMapProjects(info);
                }
            };
            ProjectService.prototype.handleSourceMapProjects = function (info) {
                // Change in d.ts, update source projects as well
                if (info.sourceMapFilePath) {
                    if (ts.isString(info.sourceMapFilePath)) {
                        var sourceMapFileInfo = this.getScriptInfoForPath(info.sourceMapFilePath);
                        this.delayUpdateSourceInfoProjects(sourceMapFileInfo && sourceMapFileInfo.sourceInfos);
                    }
                    else {
                        this.delayUpdateSourceInfoProjects(info.sourceMapFilePath.sourceInfos);
                    }
                }
                // Change in mapInfo, update declarationProjects and source projects
                this.delayUpdateSourceInfoProjects(info.sourceInfos);
                if (info.declarationInfoPath) {
                    this.delayUpdateProjectsOfScriptInfoPath(info.declarationInfoPath);
                }
            };
            ProjectService.prototype.delayUpdateSourceInfoProjects = function (sourceInfos) {
                var _this = this;
                if (sourceInfos) {
                    sourceInfos.forEach(function (_value, path) { return _this.delayUpdateProjectsOfScriptInfoPath(path); });
                }
            };
            ProjectService.prototype.delayUpdateProjectsOfScriptInfoPath = function (path) {
                var info = this.getScriptInfoForPath(path);
                if (info) {
                    this.delayUpdateProjectGraphs(info.containingProjects, /*clearSourceMapperCache*/ true);
                }
            };
            ProjectService.prototype.handleDeletedFile = function (info) {
                this.stopWatchingScriptInfo(info);
                if (!info.isScriptOpen()) {
                    this.deleteScriptInfo(info);
                    // capture list of projects since detachAllProjects will wipe out original list
                    var containingProjects = info.containingProjects.slice();
                    info.detachAllProjects();
                    // update projects to make sure that set of referenced files is correct
                    this.delayUpdateProjectGraphs(containingProjects, /*clearSourceMapperCache*/ false);
                    this.handleSourceMapProjects(info);
                    info.closeSourceMapFileWatcher();
                    // need to recalculate source map from declaration file
                    if (info.declarationInfoPath) {
                        var declarationInfo = this.getScriptInfoForPath(info.declarationInfoPath);
                        if (declarationInfo) {
                            declarationInfo.sourceMapFilePath = undefined;
                        }
                    }
                }
            };
            /**
             * This is to watch whenever files are added or removed to the wildcard directories
             */
            /*@internal*/
            ProjectService.prototype.watchWildcardDirectory = function (directory, flags, configFileName, config) {
                var _this = this;
                return this.watchFactory.watchDirectory(directory, function (fileOrDirectory) {
                    var fileOrDirectoryPath = _this.toPath(fileOrDirectory);
                    var fsResult = config.cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
                    if (ts.getBaseFileName(fileOrDirectoryPath) === "package.json" && !ts.isInsideNodeModules(fileOrDirectoryPath) &&
                        (fsResult && fsResult.fileExists || !fsResult && _this.host.fileExists(fileOrDirectoryPath))) {
                        _this.logger.info("Config: ".concat(configFileName, " Detected new package.json: ").concat(fileOrDirectory));
                        _this.onAddPackageJson(fileOrDirectoryPath);
                    }
                    var configuredProjectForConfig = _this.findConfiguredProjectByProjectName(configFileName);
                    if (ts.isIgnoredFileFromWildCardWatching({
                        watchedDirPath: directory,
                        fileOrDirectory: fileOrDirectory,
                        fileOrDirectoryPath: fileOrDirectoryPath,
                        configFileName: configFileName,
                        extraFileExtensions: _this.hostConfiguration.extraFileExtensions,
                        currentDirectory: _this.currentDirectory,
                        options: config.parsedCommandLine.options,
                        program: (configuredProjectForConfig === null || configuredProjectForConfig === void 0 ? void 0 : configuredProjectForConfig.getCurrentProgram()) || config.parsedCommandLine.fileNames,
                        useCaseSensitiveFileNames: _this.host.useCaseSensitiveFileNames,
                        writeLog: function (s) { return _this.logger.info(s); },
                        toPath: function (s) { return _this.toPath(s); }
                    }))
                        return;
                    // Reload is pending, do the reload
                    if (config.reloadLevel !== ts.ConfigFileProgramReloadLevel.Full)
                        config.reloadLevel = ts.ConfigFileProgramReloadLevel.Partial;
                    config.projects.forEach(function (watchWildcardDirectories, projectCanonicalPath) {
                        if (!watchWildcardDirectories)
                            return;
                        var project = _this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath);
                        if (!project)
                            return;
                        // Load root file names for configured project with the config file name
                        // But only schedule update if project references this config file
                        var reloadLevel = configuredProjectForConfig === project ? ts.ConfigFileProgramReloadLevel.Partial : ts.ConfigFileProgramReloadLevel.None;
                        if (project.pendingReload !== undefined && project.pendingReload > reloadLevel)
                            return;
                        // don't trigger callback on open, existing files
                        if (_this.openFiles.has(fileOrDirectoryPath)) {
                            var info = ts.Debug.checkDefined(_this.getScriptInfoForPath(fileOrDirectoryPath));
                            if (info.isAttached(project)) {
                                var loadLevelToSet = Math.max(reloadLevel, project.openFileWatchTriggered.get(fileOrDirectoryPath) || ts.ConfigFileProgramReloadLevel.None);
                                project.openFileWatchTriggered.set(fileOrDirectoryPath, loadLevelToSet);
                            }
                            else {
                                project.pendingReload = reloadLevel;
                                _this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project);
                            }
                        }
                        else {
                            project.pendingReload = reloadLevel;
                            _this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project);
                        }
                    });
                }, flags, this.getWatchOptionsFromProjectWatchOptions(config.parsedCommandLine.watchOptions), ts.WatchType.WildcardDirectory, configFileName);
            };
            /*@internal*/
            ProjectService.prototype.delayUpdateProjectsFromParsedConfigOnConfigFileChange = function (canonicalConfigFilePath, reloadReason) {
                var _this = this;
                var configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                if (!(configFileExistenceInfo === null || configFileExistenceInfo === void 0 ? void 0 : configFileExistenceInfo.config))
                    return false;
                var scheduledAnyProjectUpdate = false;
                // Update projects watching cached config
                configFileExistenceInfo.config.reloadLevel = ts.ConfigFileProgramReloadLevel.Full;
                configFileExistenceInfo.config.projects.forEach(function (_watchWildcardDirectories, projectCanonicalPath) {
                    var project = _this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath);
                    if (!project)
                        return;
                    scheduledAnyProjectUpdate = true;
                    if (projectCanonicalPath === canonicalConfigFilePath) {
                        // Skip refresh if project is not yet loaded
                        if (project.isInitialLoadPending())
                            return;
                        project.pendingReload = ts.ConfigFileProgramReloadLevel.Full;
                        project.pendingReloadReason = reloadReason;
                        _this.delayUpdateProjectGraph(project);
                    }
                    else {
                        // Change in referenced project config file
                        project.resolutionCache.removeResolutionsFromProjectReferenceRedirects(_this.toPath(canonicalConfigFilePath));
                        _this.delayUpdateProjectGraph(project);
                    }
                });
                return scheduledAnyProjectUpdate;
            };
            /*@internal*/
            ProjectService.prototype.onConfigFileChanged = function (canonicalConfigFilePath, eventKind) {
                var _a;
                var configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                if (eventKind === ts.FileWatcherEventKind.Deleted) {
                    // Update the cached status
                    // We arent updating or removing the cached config file presence info as that will be taken care of by
                    // releaseParsedConfig when the project is closed or doesnt need this config any more (depending on tracking open files)
                    configFileExistenceInfo.exists = false;
                    // Remove the configured project for this config file
                    var project = ((_a = configFileExistenceInfo.config) === null || _a === void 0 ? void 0 : _a.projects.has(canonicalConfigFilePath)) ?
                        this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath) :
                        undefined;
                    if (project)
                        this.removeProject(project);
                }
                else {
                    // Update the cached status
                    configFileExistenceInfo.exists = true;
                }
                // Update projects watching config
                this.delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalConfigFilePath, "Change in config file detected");
                // Reload the configured projects for the open files in the map as they are affected by this config file
                // If the configured project was deleted, we want to reload projects for all the open files including files
                // that are not root of the inferred project
                // Otherwise, we scheduled the update on configured project graph,
                // we would need to schedule the project reload for only the root of inferred projects
                // Get open files to reload projects for
                this.reloadConfiguredProjectForFiles(configFileExistenceInfo.openFilesImpactedByConfigFile, 
                /*clearSemanticCache*/ false, 
                /*delayReload*/ true, eventKind !== ts.FileWatcherEventKind.Deleted ?
                    ts.identity : // Reload open files if they are root of inferred project
                    ts.returnTrue, // Reload all the open files impacted by config file
                "Change in config file detected");
                this.delayEnsureProjectForOpenFiles();
            };
            ProjectService.prototype.removeProject = function (project) {
                var _this = this;
                this.logger.info("`remove Project::");
                project.print(/*writeProjectFileNames*/ true);
                project.close();
                if (ts.Debug.shouldAssert(1 /* AssertionLevel.Normal */)) {
                    this.filenameToScriptInfo.forEach(function (info) { return ts.Debug.assert(!info.isAttached(project), "Found script Info still attached to project", function () { return "".concat(project.projectName, ": ScriptInfos still attached: ").concat(JSON.stringify(ts.arrayFrom(ts.mapDefinedIterator(_this.filenameToScriptInfo.values(), function (info) { return info.isAttached(project) ?
                        {
                            fileName: info.fileName,
                            projects: info.containingProjects.map(function (p) { return p.projectName; }),
                            hasMixedContent: info.hasMixedContent
                        } : undefined; })), 
                    /*replacer*/ undefined, " ")); }); });
                }
                // Remove the project from pending project updates
                this.pendingProjectUpdates.delete(project.getProjectName());
                switch (project.projectKind) {
                    case server.ProjectKind.External:
                        ts.unorderedRemoveItem(this.externalProjects, project);
                        this.projectToSizeMap.delete(project.getProjectName());
                        break;
                    case server.ProjectKind.Configured:
                        this.configuredProjects.delete(project.canonicalConfigFilePath);
                        this.projectToSizeMap.delete(project.canonicalConfigFilePath);
                        break;
                    case server.ProjectKind.Inferred:
                        ts.unorderedRemoveItem(this.inferredProjects, project);
                        break;
                }
            };
            /*@internal*/
            ProjectService.prototype.assignOrphanScriptInfoToInferredProject = function (info, projectRootPath) {
                ts.Debug.assert(info.isOrphan());
                var project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) ||
                    this.getOrCreateSingleInferredProjectIfEnabled() ||
                    this.getOrCreateSingleInferredWithoutProjectRoot(info.isDynamic ?
                        projectRootPath || this.currentDirectory :
                        ts.getDirectoryPath(ts.isRootedDiskPath(info.fileName) ?
                            info.fileName :
                            ts.getNormalizedAbsolutePath(info.fileName, projectRootPath ?
                                this.getNormalizedAbsolutePath(projectRootPath) :
                                this.currentDirectory)));
                project.addRoot(info);
                if (info.containingProjects[0] !== project) {
                    // Ensure this is first project, we could be in this scenario because info could be part of orphan project
                    info.detachFromProject(project);
                    info.containingProjects.unshift(project);
                }
                project.updateGraph();
                if (!this.useSingleInferredProject && !project.projectRootPath) {
                    var _loop_3 = function (inferredProject) {
                        if (inferredProject === project || inferredProject.isOrphan()) {
                            return "continue";
                        }
                        // Remove the inferred project if the root of it is now part of newly created inferred project
                        // e.g through references
                        // Which means if any root of inferred project is part of more than 1 project can be removed
                        // This logic is same as iterating over all open files and calling
                        // this.removeRootOfInferredProjectIfNowPartOfOtherProject(f);
                        // Since this is also called from refreshInferredProject and closeOpen file
                        // to update inferred projects of the open file, this iteration might be faster
                        // instead of scanning all open files
                        var roots = inferredProject.getRootScriptInfos();
                        ts.Debug.assert(roots.length === 1 || !!inferredProject.projectRootPath);
                        if (roots.length === 1 && ts.forEach(roots[0].containingProjects, function (p) { return p !== roots[0].containingProjects[0] && !p.isOrphan(); })) {
                            inferredProject.removeFile(roots[0], /*fileExists*/ true, /*detachFromProject*/ true);
                        }
                    };
                    // Note that we need to create a copy of the array since the list of project can change
                    for (var _i = 0, _a = this.inferredProjects; _i < _a.length; _i++) {
                        var inferredProject = _a[_i];
                        _loop_3(inferredProject);
                    }
                }
                return project;
            };
            ProjectService.prototype.assignOrphanScriptInfosToInferredProject = function () {
                var _this = this;
                // collect orphaned files and assign them to inferred project just like we treat open of a file
                this.openFiles.forEach(function (projectRootPath, path) {
                    var info = _this.getScriptInfoForPath(path);
                    // collect all orphaned script infos from open files
                    if (info.isOrphan()) {
                        _this.assignOrphanScriptInfoToInferredProject(info, projectRootPath);
                    }
                });
            };
            /**
             * Remove this file from the set of open, non-configured files.
             * @param info The file that has been closed or newly configured
             */
            ProjectService.prototype.closeOpenFile = function (info, skipAssignOrphanScriptInfosToInferredProject) {
                // Closing file should trigger re-reading the file content from disk. This is
                // because the user may chose to discard the buffer content before saving
                // to the disk, and the server's version of the file can be out of sync.
                var fileExists = info.isDynamic ? false : this.host.fileExists(info.fileName);
                info.close(fileExists);
                this.stopWatchingConfigFilesForClosedScriptInfo(info);
                var canonicalFileName = this.toCanonicalFileName(info.fileName);
                if (this.openFilesWithNonRootedDiskPath.get(canonicalFileName) === info) {
                    this.openFilesWithNonRootedDiskPath.delete(canonicalFileName);
                }
                // collect all projects that should be removed
                var ensureProjectsForOpenFiles = false;
                for (var _i = 0, _a = info.containingProjects; _i < _a.length; _i++) {
                    var p = _a[_i];
                    if (server.isConfiguredProject(p)) {
                        if (info.hasMixedContent) {
                            info.registerFileUpdate();
                        }
                        // Do not remove the project so that we can reuse this project
                        // if it would need to be re-created with next file open
                        // If project had open file affecting
                        // Reload the root Files from config if its not already scheduled
                        var reloadLevel = p.openFileWatchTriggered.get(info.path);
                        if (reloadLevel !== undefined) {
                            p.openFileWatchTriggered.delete(info.path);
                            if (p.pendingReload !== undefined && p.pendingReload < reloadLevel) {
                                p.pendingReload = reloadLevel;
                                p.markFileAsDirty(info.path);
                            }
                        }
                    }
                    else if (server.isInferredProject(p) && p.isRoot(info)) {
                        // If this was the last open root file of inferred project
                        if (p.isProjectWithSingleRoot()) {
                            ensureProjectsForOpenFiles = true;
                        }
                        p.removeFile(info, fileExists, /*detachFromProject*/ true);
                        // Do not remove the project even if this was last root of the inferred project
                        // so that we can reuse this project, if it would need to be re-created with next file open
                    }
                    if (!p.languageServiceEnabled) {
                        // if project language service is disabled then we create a program only for open files.
                        // this means that project should be marked as dirty to force rebuilding of the program
                        // on the next request
                        p.markAsDirty();
                    }
                }
                this.openFiles.delete(info.path);
                this.configFileForOpenFiles.delete(info.path);
                if (!skipAssignOrphanScriptInfosToInferredProject && ensureProjectsForOpenFiles) {
                    this.assignOrphanScriptInfosToInferredProject();
                }
                // Cleanup script infos that arent part of any project (eg. those could be closed script infos not referenced by any project)
                // is postponed to next file open so that if file from same project is opened,
                // we wont end up creating same script infos
                // If the current info is being just closed - add the watcher file to track changes
                // But if file was deleted, handle that part
                if (fileExists) {
                    this.watchClosedScriptInfo(info);
                }
                else {
                    this.handleDeletedFile(info);
                }
                return ensureProjectsForOpenFiles;
            };
            ProjectService.prototype.deleteScriptInfo = function (info) {
                this.filenameToScriptInfo.delete(info.path);
                this.filenameToScriptInfoVersion.set(info.path, info.getVersion());
                var realpath = info.getRealpathIfDifferent();
                if (realpath) {
                    this.realpathToScriptInfos.remove(realpath, info); // TODO: GH#18217
                }
            };
            ProjectService.prototype.configFileExists = function (configFileName, canonicalConfigFilePath, info) {
                var _a;
                var configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                if (configFileExistenceInfo) {
                    // By default the info would get impacted by presence of config file since its in the detection path
                    // Only adding the info as a root to inferred project will need the existence to be watched by file watcher
                    if (isOpenScriptInfo(info) && !((_a = configFileExistenceInfo.openFilesImpactedByConfigFile) === null || _a === void 0 ? void 0 : _a.has(info.path))) {
                        (configFileExistenceInfo.openFilesImpactedByConfigFile || (configFileExistenceInfo.openFilesImpactedByConfigFile = new ts.Map())).set(info.path, false);
                    }
                    return configFileExistenceInfo.exists;
                }
                // Theoretically we should be adding watch for the directory here itself.
                // In practice there will be very few scenarios where the config file gets added
                // somewhere inside the another config file directory.
                // And technically we could handle that case in configFile's directory watcher in some cases
                // But given that its a rare scenario it seems like too much overhead. (we werent watching those directories earlier either)
                // So what we are now watching is: configFile if the configured project corresponding to it is open
                // Or the whole chain of config files for the roots of the inferred projects
                // Cache the host value of file exists and add the info to map of open files impacted by this config file
                var exists = this.host.fileExists(configFileName);
                var openFilesImpactedByConfigFile;
                if (isOpenScriptInfo(info)) {
                    (openFilesImpactedByConfigFile || (openFilesImpactedByConfigFile = new ts.Map())).set(info.path, false);
                }
                configFileExistenceInfo = { exists: exists, openFilesImpactedByConfigFile: openFilesImpactedByConfigFile };
                this.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo);
                return exists;
            };
            /*@internal*/
            ProjectService.prototype.createConfigFileWatcherForParsedConfig = function (configFileName, canonicalConfigFilePath, forProject) {
                var _this = this;
                var _a, _b;
                var configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                // When watching config file for parsed config, remove the noopFileWatcher that can be created for open files impacted by config file and watch for real
                if (!configFileExistenceInfo.watcher || configFileExistenceInfo.watcher === noopConfigFileWatcher) {
                    configFileExistenceInfo.watcher = this.watchFactory.watchFile(configFileName, function (_fileName, eventKind) { return _this.onConfigFileChanged(canonicalConfigFilePath, eventKind); }, ts.PollingInterval.High, this.getWatchOptionsFromProjectWatchOptions((_b = (_a = configFileExistenceInfo === null || configFileExistenceInfo === void 0 ? void 0 : configFileExistenceInfo.config) === null || _a === void 0 ? void 0 : _a.parsedCommandLine) === null || _b === void 0 ? void 0 : _b.watchOptions), ts.WatchType.ConfigFile, forProject);
                }
                // Watching config file for project, update the map
                var projects = configFileExistenceInfo.config.projects;
                projects.set(forProject.canonicalConfigFilePath, projects.get(forProject.canonicalConfigFilePath) || false);
            };
            /**
             * Returns true if the configFileExistenceInfo is needed/impacted by open files that are root of inferred project
             */
            ProjectService.prototype.configFileExistenceImpactsRootOfInferredProject = function (configFileExistenceInfo) {
                return configFileExistenceInfo.openFilesImpactedByConfigFile &&
                    ts.forEachEntry(configFileExistenceInfo.openFilesImpactedByConfigFile, ts.identity);
            };
            /* @internal */
            ProjectService.prototype.releaseParsedConfig = function (canonicalConfigFilePath, forProject) {
                var _a, _b, _c;
                var configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                if (!((_a = configFileExistenceInfo.config) === null || _a === void 0 ? void 0 : _a.projects.delete(forProject.canonicalConfigFilePath)))
                    return;
                // If there are still projects watching this config file existence and config, there is nothing to do
                if ((_b = configFileExistenceInfo.config) === null || _b === void 0 ? void 0 : _b.projects.size)
                    return;
                configFileExistenceInfo.config = undefined;
                ts.clearSharedExtendedConfigFileWatcher(canonicalConfigFilePath, this.sharedExtendedConfigFileWatchers);
                ts.Debug.checkDefined(configFileExistenceInfo.watcher);
                if ((_c = configFileExistenceInfo.openFilesImpactedByConfigFile) === null || _c === void 0 ? void 0 : _c.size) {
                    // If there are open files that are impacted by this config file existence
                    // but none of them are root of inferred project, the config file watcher will be
                    // created when any of the script infos are added as root of inferred project
                    if (this.configFileExistenceImpactsRootOfInferredProject(configFileExistenceInfo)) {
                        // If we cannot watch config file existence without configured project, close the configured file watcher
                        if (!ts.canWatchDirectory(ts.getDirectoryPath(canonicalConfigFilePath))) {
                            configFileExistenceInfo.watcher.close();
                            configFileExistenceInfo.watcher = noopConfigFileWatcher;
                        }
                    }
                    else {
                        // Close existing watcher
                        configFileExistenceInfo.watcher.close();
                        configFileExistenceInfo.watcher = undefined;
                    }
                }
                else {
                    // There is not a single file open thats tracking the status of this config file. Remove from cache
                    configFileExistenceInfo.watcher.close();
                    this.configFileExistenceInfoCache.delete(canonicalConfigFilePath);
                }
            };
            /**
             * Close the config file watcher in the cached ConfigFileExistenceInfo
             *   if there arent any open files that are root of inferred project and there is no parsed config held by any project
             */
            /*@internal*/
            ProjectService.prototype.closeConfigFileWatcherOnReleaseOfOpenFile = function (configFileExistenceInfo) {
                // Close the config file watcher if there are no more open files that are root of inferred project
                // or if there are no projects that need to watch this config file existence info
                if (configFileExistenceInfo.watcher &&
                    !configFileExistenceInfo.config &&
                    !this.configFileExistenceImpactsRootOfInferredProject(configFileExistenceInfo)) {
                    configFileExistenceInfo.watcher.close();
                    configFileExistenceInfo.watcher = undefined;
                }
            };
            /**
             * This is called on file close, so that we stop watching the config file for this script info
             */
            ProjectService.prototype.stopWatchingConfigFilesForClosedScriptInfo = function (info) {
                var _this = this;
                ts.Debug.assert(!info.isScriptOpen());
                this.forEachConfigFileLocation(info, function (canonicalConfigFilePath) {
                    var _a, _b, _c;
                    var configFileExistenceInfo = _this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                    if (configFileExistenceInfo) {
                        var infoIsRootOfInferredProject = (_a = configFileExistenceInfo.openFilesImpactedByConfigFile) === null || _a === void 0 ? void 0 : _a.get(info.path);
                        // Delete the info from map, since this file is no more open
                        (_b = configFileExistenceInfo.openFilesImpactedByConfigFile) === null || _b === void 0 ? void 0 : _b.delete(info.path);
                        // If the script info was not root of inferred project,
                        // there wont be config file watch open because of this script info
                        if (infoIsRootOfInferredProject) {
                            // But if it is a root, it could be the last script info that is root of inferred project
                            // and hence we would need to close the config file watcher
                            _this.closeConfigFileWatcherOnReleaseOfOpenFile(configFileExistenceInfo);
                        }
                        // If there are no open files that are impacted by configFileExistenceInfo after closing this script info
                        // and there is are no projects that need the config file existence or parsed config,
                        // remove the cached existence info
                        if (!((_c = configFileExistenceInfo.openFilesImpactedByConfigFile) === null || _c === void 0 ? void 0 : _c.size) &&
                            !configFileExistenceInfo.config) {
                            ts.Debug.assert(!configFileExistenceInfo.watcher);
                            _this.configFileExistenceInfoCache.delete(canonicalConfigFilePath);
                        }
                    }
                });
            };
            /**
             * This is called by inferred project whenever script info is added as a root
             */
            /* @internal */
            ProjectService.prototype.startWatchingConfigFilesForInferredProjectRoot = function (info) {
                var _this = this;
                ts.Debug.assert(info.isScriptOpen());
                this.forEachConfigFileLocation(info, function (canonicalConfigFilePath, configFileName) {
                    var configFileExistenceInfo = _this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                    if (!configFileExistenceInfo) {
                        // Create the cache
                        configFileExistenceInfo = { exists: _this.host.fileExists(configFileName) };
                        _this.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo);
                    }
                    // Set this file as the root of inferred project
                    (configFileExistenceInfo.openFilesImpactedByConfigFile || (configFileExistenceInfo.openFilesImpactedByConfigFile = new ts.Map())).set(info.path, true);
                    // If there is no configured project for this config file, add the file watcher
                    configFileExistenceInfo.watcher || (configFileExistenceInfo.watcher = ts.canWatchDirectory(ts.getDirectoryPath(canonicalConfigFilePath)) ?
                        _this.watchFactory.watchFile(configFileName, function (_filename, eventKind) { return _this.onConfigFileChanged(canonicalConfigFilePath, eventKind); }, ts.PollingInterval.High, _this.hostConfiguration.watchOptions, ts.WatchType.ConfigFileForInferredRoot) :
                        noopConfigFileWatcher);
                });
            };
            /**
             * This is called by inferred project whenever root script info is removed from it
             */
            /* @internal */
            ProjectService.prototype.stopWatchingConfigFilesForInferredProjectRoot = function (info) {
                var _this = this;
                this.forEachConfigFileLocation(info, function (canonicalConfigFilePath) {
                    var _a;
                    var configFileExistenceInfo = _this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                    if ((_a = configFileExistenceInfo === null || configFileExistenceInfo === void 0 ? void 0 : configFileExistenceInfo.openFilesImpactedByConfigFile) === null || _a === void 0 ? void 0 : _a.has(info.path)) {
                        ts.Debug.assert(info.isScriptOpen());
                        // Info is not root of inferred project any more
                        configFileExistenceInfo.openFilesImpactedByConfigFile.set(info.path, false);
                        // Close the config file watcher
                        _this.closeConfigFileWatcherOnReleaseOfOpenFile(configFileExistenceInfo);
                    }
                });
            };
            /**
             * This function tries to search for a tsconfig.json for the given file.
             * This is different from the method the compiler uses because
             * the compiler can assume it will always start searching in the
             * current directory (the directory in which tsc was invoked).
             * The server must start searching from the directory containing
             * the newly opened file.
             */
            ProjectService.prototype.forEachConfigFileLocation = function (info, action) {
                var _this = this;
                if (this.serverMode !== ts.LanguageServiceMode.Semantic) {
                    return undefined;
                }
                ts.Debug.assert(!isOpenScriptInfo(info) || this.openFiles.has(info.path));
                var projectRootPath = this.openFiles.get(info.path);
                var scriptInfo = ts.Debug.checkDefined(this.getScriptInfo(info.path));
                if (scriptInfo.isDynamic)
                    return undefined;
                var searchPath = server.asNormalizedPath(ts.getDirectoryPath(info.fileName));
                var isSearchPathInProjectRoot = function () { return ts.containsPath(projectRootPath, searchPath, _this.currentDirectory, !_this.host.useCaseSensitiveFileNames); };
                // If projectRootPath doesn't contain info.path, then do normal search for config file
                var anySearchPathOk = !projectRootPath || !isSearchPathInProjectRoot();
                // For ancestor of config file always ignore its own directory since its going to result in itself
                var searchInDirectory = !isAncestorConfigFileInfo(info);
                do {
                    if (searchInDirectory) {
                        var canonicalSearchPath = server.normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName);
                        var tsconfigFileName = server.asNormalizedPath(ts.combinePaths(searchPath, "tsconfig.json"));
                        var result = action(ts.combinePaths(canonicalSearchPath, "tsconfig.json"), tsconfigFileName);
                        if (result)
                            return tsconfigFileName;
                        var jsconfigFileName = server.asNormalizedPath(ts.combinePaths(searchPath, "jsconfig.json"));
                        result = action(ts.combinePaths(canonicalSearchPath, "jsconfig.json"), jsconfigFileName);
                        if (result)
                            return jsconfigFileName;
                        // If we started within node_modules, don't look outside node_modules.
                        // Otherwise, we might pick up a very large project and pull in the world,
                        // causing an editor delay.
                        if (ts.isNodeModulesDirectory(canonicalSearchPath)) {
                            break;
                        }
                    }
                    var parentPath = server.asNormalizedPath(ts.getDirectoryPath(searchPath));
                    if (parentPath === searchPath)
                        break;
                    searchPath = parentPath;
                    searchInDirectory = true;
                } while (anySearchPathOk || isSearchPathInProjectRoot());
                return undefined;
            };
            /*@internal*/
            ProjectService.prototype.findDefaultConfiguredProject = function (info) {
                if (!info.isScriptOpen())
                    return undefined;
                var configFileName = this.getConfigFileNameForFile(info);
                var project = configFileName &&
                    this.findConfiguredProjectByProjectName(configFileName);
                return project && projectContainsInfoDirectly(project, info) ?
                    project :
                    project === null || project === void 0 ? void 0 : project.getDefaultChildProjectFromProjectWithReferences(info);
            };
            /**
             * This function tries to search for a tsconfig.json for the given file.
             * This is different from the method the compiler uses because
             * the compiler can assume it will always start searching in the
             * current directory (the directory in which tsc was invoked).
             * The server must start searching from the directory containing
             * the newly opened file.
             * If script info is passed in, it is asserted to be open script info
             * otherwise just file name
             */
            ProjectService.prototype.getConfigFileNameForFile = function (info) {
                var _this = this;
                if (isOpenScriptInfo(info)) {
                    ts.Debug.assert(info.isScriptOpen());
                    var result = this.configFileForOpenFiles.get(info.path);
                    if (result !== undefined)
                        return result || undefined;
                }
                this.logger.info("Search path: ".concat(ts.getDirectoryPath(info.fileName)));
                var configFileName = this.forEachConfigFileLocation(info, function (canonicalConfigFilePath, configFileName) {
                    return _this.configFileExists(configFileName, canonicalConfigFilePath, info);
                });
                if (configFileName) {
                    this.logger.info("For info: ".concat(info.fileName, " :: Config file name: ").concat(configFileName));
                }
                else {
                    this.logger.info("For info: ".concat(info.fileName, " :: No config files found."));
                }
                if (isOpenScriptInfo(info)) {
                    this.configFileForOpenFiles.set(info.path, configFileName || false);
                }
                return configFileName;
            };
            ProjectService.prototype.printProjects = function () {
                var _this = this;
                if (!this.logger.hasLevel(server.LogLevel.normal)) {
                    return;
                }
                this.logger.startGroup();
                this.externalProjects.forEach(printProjectWithoutFileNames);
                this.configuredProjects.forEach(printProjectWithoutFileNames);
                this.inferredProjects.forEach(printProjectWithoutFileNames);
                this.logger.info("Open files: ");
                this.openFiles.forEach(function (projectRootPath, path) {
                    var info = _this.getScriptInfoForPath(path);
                    _this.logger.info("\tFileName: ".concat(info.fileName, " ProjectRootPath: ").concat(projectRootPath));
                    _this.logger.info("\t\tProjects: ".concat(info.containingProjects.map(function (p) { return p.getProjectName(); })));
                });
                this.logger.endGroup();
            };
            /*@internal*/
            ProjectService.prototype.findConfiguredProjectByProjectName = function (configFileName) {
                // make sure that casing of config file name is consistent
                var canonicalConfigFilePath = server.asNormalizedPath(this.toCanonicalFileName(configFileName));
                return this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath);
            };
            ProjectService.prototype.getConfiguredProjectByCanonicalConfigFilePath = function (canonicalConfigFilePath) {
                return this.configuredProjects.get(canonicalConfigFilePath);
            };
            ProjectService.prototype.findExternalProjectByProjectName = function (projectFileName) {
                return findProjectByName(projectFileName, this.externalProjects);
            };
            /** Get a filename if the language service exceeds the maximum allowed program size; otherwise returns undefined. */
            ProjectService.prototype.getFilenameForExceededTotalSizeLimitForNonTsFiles = function (name, options, fileNames, propertyReader) {
                var _this = this;
                if (options && options.disableSizeLimit || !this.host.getFileSize) {
                    return;
                }
                var availableSpace = server.maxProgramSizeForNonTsFiles;
                this.projectToSizeMap.set(name, 0);
                this.projectToSizeMap.forEach(function (val) { return (availableSpace -= (val || 0)); });
                var totalNonTsFileSize = 0;
                for (var _i = 0, fileNames_1 = fileNames; _i < fileNames_1.length; _i++) {
                    var f = fileNames_1[_i];
                    var fileName = propertyReader.getFileName(f);
                    if (ts.hasTSFileExtension(fileName)) {
                        continue;
                    }
                    totalNonTsFileSize += this.host.getFileSize(fileName);
                    if (totalNonTsFileSize > server.maxProgramSizeForNonTsFiles || totalNonTsFileSize > availableSpace) {
                        var top5LargestFiles = fileNames.map(function (f) { return propertyReader.getFileName(f); })
                            .filter(function (name) { return !ts.hasTSFileExtension(name); })
                            .map(function (name) { return ({ name: name, size: _this.host.getFileSize(name) }); })
                            .sort(function (a, b) { return b.size - a.size; })
                            .slice(0, 5);
                        this.logger.info("Non TS file size exceeded limit (".concat(totalNonTsFileSize, "). Largest files: ").concat(top5LargestFiles.map(function (file) { return "".concat(file.name, ":").concat(file.size); }).join(", ")));
                        // Keep the size as zero since it's disabled
                        return fileName;
                    }
                }
                this.projectToSizeMap.set(name, totalNonTsFileSize);
            };
            ProjectService.prototype.createExternalProject = function (projectFileName, files, options, typeAcquisition, excludedFiles) {
                var compilerOptions = convertCompilerOptions(options);
                var watchOptionsAndErrors = convertWatchOptions(options, ts.getDirectoryPath(ts.normalizeSlashes(projectFileName)));
                var project = new server.ExternalProject(projectFileName, this, this.documentRegistry, compilerOptions, 
                /*lastFileExceededProgramSize*/ this.getFilenameForExceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader), options.compileOnSave === undefined ? true : options.compileOnSave, 
                /*projectFilePath*/ undefined, this.currentPluginConfigOverrides, watchOptionsAndErrors === null || watchOptionsAndErrors === void 0 ? void 0 : watchOptionsAndErrors.watchOptions);
                project.setProjectErrors(watchOptionsAndErrors === null || watchOptionsAndErrors === void 0 ? void 0 : watchOptionsAndErrors.errors);
                project.excludedFiles = excludedFiles;
                this.addFilesToNonInferredProject(project, files, externalFilePropertyReader, typeAcquisition);
                this.externalProjects.push(project);
                return project;
            };
            /*@internal*/
            ProjectService.prototype.sendProjectTelemetry = function (project) {
                if (this.seenProjects.has(project.projectName)) {
                    setProjectOptionsUsed(project);
                    return;
                }
                this.seenProjects.set(project.projectName, true);
                if (!this.eventHandler || !this.host.createSHA256Hash) {
                    setProjectOptionsUsed(project);
                    return;
                }
                var projectOptions = server.isConfiguredProject(project) ? project.projectOptions : undefined;
                setProjectOptionsUsed(project);
                var data = {
                    projectId: this.host.createSHA256Hash(project.projectName),
                    fileStats: server.countEachFileTypes(project.getScriptInfos(), /*includeSizes*/ true),
                    compilerOptions: ts.convertCompilerOptionsForTelemetry(project.getCompilationSettings()),
                    typeAcquisition: convertTypeAcquisition(project.getTypeAcquisition()),
                    extends: projectOptions && projectOptions.configHasExtendsProperty,
                    files: projectOptions && projectOptions.configHasFilesProperty,
                    include: projectOptions && projectOptions.configHasIncludeProperty,
                    exclude: projectOptions && projectOptions.configHasExcludeProperty,
                    compileOnSave: project.compileOnSaveEnabled,
                    configFileName: configFileName(),
                    projectType: project instanceof server.ExternalProject ? "external" : "configured",
                    languageServiceEnabled: project.languageServiceEnabled,
                    version: ts.version, // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier
                };
                this.eventHandler({ eventName: server.ProjectInfoTelemetryEvent, data: data });
                function configFileName() {
                    if (!server.isConfiguredProject(project)) {
                        return "other";
                    }
                    return server.getBaseConfigFileName(project.getConfigFilePath()) || "other";
                }
                function convertTypeAcquisition(_a) {
                    var enable = _a.enable, include = _a.include, exclude = _a.exclude;
                    return {
                        enable: enable,
                        include: include !== undefined && include.length !== 0,
                        exclude: exclude !== undefined && exclude.length !== 0,
                    };
                }
            };
            ProjectService.prototype.addFilesToNonInferredProject = function (project, files, propertyReader, typeAcquisition) {
                this.updateNonInferredProjectFiles(project, files, propertyReader);
                project.setTypeAcquisition(typeAcquisition);
            };
            /* @internal */
            ProjectService.prototype.createConfiguredProject = function (configFileName) {
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "createConfiguredProject", { configFilePath: configFileName });
                this.logger.info("Creating configuration project ".concat(configFileName));
                var canonicalConfigFilePath = server.asNormalizedPath(this.toCanonicalFileName(configFileName));
                var configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                // We could be in this scenario if project is the configured project tracked by external project
                // Since that route doesnt check if the config file is present or not
                if (!configFileExistenceInfo) {
                    this.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo = { exists: true });
                }
                else {
                    configFileExistenceInfo.exists = true;
                }
                if (!configFileExistenceInfo.config) {
                    configFileExistenceInfo.config = {
                        cachedDirectoryStructureHost: ts.createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames),
                        projects: new ts.Map(),
                        reloadLevel: ts.ConfigFileProgramReloadLevel.Full
                    };
                }
                var project = new server.ConfiguredProject(configFileName, canonicalConfigFilePath, this, this.documentRegistry, configFileExistenceInfo.config.cachedDirectoryStructureHost);
                this.configuredProjects.set(canonicalConfigFilePath, project);
                this.createConfigFileWatcherForParsedConfig(configFileName, canonicalConfigFilePath, project);
                return project;
            };
            /* @internal */
            ProjectService.prototype.createConfiguredProjectWithDelayLoad = function (configFileName, reason) {
                var project = this.createConfiguredProject(configFileName);
                project.pendingReload = ts.ConfigFileProgramReloadLevel.Full;
                project.pendingReloadReason = reason;
                return project;
            };
            /* @internal */
            ProjectService.prototype.createAndLoadConfiguredProject = function (configFileName, reason) {
                var project = this.createConfiguredProject(configFileName);
                this.loadConfiguredProject(project, reason);
                return project;
            };
            /* @internal */
            ProjectService.prototype.createLoadAndUpdateConfiguredProject = function (configFileName, reason) {
                var project = this.createAndLoadConfiguredProject(configFileName, reason);
                project.updateGraph();
                return project;
            };
            /**
             * Read the config file of the project, and update the project root file names.
             */
            /* @internal */
            ProjectService.prototype.loadConfiguredProject = function (project, reason) {
                var _this = this;
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "loadConfiguredProject", { configFilePath: project.canonicalConfigFilePath });
                this.sendProjectLoadingStartEvent(project, reason);
                // Read updated contents from disk
                var configFilename = server.asNormalizedPath(ts.normalizePath(project.getConfigFilePath()));
                var configFileExistenceInfo = this.ensureParsedConfigUptoDate(configFilename, project.canonicalConfigFilePath, this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath), project);
                var parsedCommandLine = configFileExistenceInfo.config.parsedCommandLine;
                ts.Debug.assert(!!parsedCommandLine.fileNames);
                var compilerOptions = parsedCommandLine.options;
                // Update the project
                if (!project.projectOptions) {
                    project.projectOptions = {
                        configHasExtendsProperty: parsedCommandLine.raw.extends !== undefined,
                        configHasFilesProperty: parsedCommandLine.raw.files !== undefined,
                        configHasIncludeProperty: parsedCommandLine.raw.include !== undefined,
                        configHasExcludeProperty: parsedCommandLine.raw.exclude !== undefined
                    };
                }
                project.canConfigFileJsonReportNoInputFiles = ts.canJsonReportNoInputFiles(parsedCommandLine.raw);
                project.setProjectErrors(parsedCommandLine.options.configFile.parseDiagnostics);
                project.updateReferences(parsedCommandLine.projectReferences);
                var lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, compilerOptions, parsedCommandLine.fileNames, fileNamePropertyReader);
                if (lastFileExceededProgramSize) {
                    project.disableLanguageService(lastFileExceededProgramSize);
                    this.configFileExistenceInfoCache.forEach(function (_configFileExistenceInfo, canonicalConfigFilePath) {
                        return _this.stopWatchingWildCards(canonicalConfigFilePath, project);
                    });
                }
                else {
                    project.setCompilerOptions(compilerOptions);
                    project.setWatchOptions(parsedCommandLine.watchOptions);
                    project.enableLanguageService();
                    this.watchWildcards(configFilename, configFileExistenceInfo, project);
                }
                project.enablePluginsWithOptions(compilerOptions, this.currentPluginConfigOverrides);
                var filesToAdd = parsedCommandLine.fileNames.concat(project.getExternalFiles());
                this.updateRootAndOptionsOfNonInferredProject(project, filesToAdd, fileNamePropertyReader, compilerOptions, parsedCommandLine.typeAcquisition, parsedCommandLine.compileOnSave, parsedCommandLine.watchOptions);
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
            };
            /*@internal*/
            ProjectService.prototype.ensureParsedConfigUptoDate = function (configFilename, canonicalConfigFilePath, configFileExistenceInfo, forProject) {
                var _this = this;
                var _a, _b, _c;
                if (configFileExistenceInfo.config) {
                    if (!configFileExistenceInfo.config.reloadLevel)
                        return configFileExistenceInfo;
                    if (configFileExistenceInfo.config.reloadLevel === ts.ConfigFileProgramReloadLevel.Partial) {
                        this.reloadFileNamesOfParsedConfig(configFilename, configFileExistenceInfo.config);
                        return configFileExistenceInfo;
                    }
                }
                // Parse the config file and ensure its cached
                var cachedDirectoryStructureHost = ((_a = configFileExistenceInfo.config) === null || _a === void 0 ? void 0 : _a.cachedDirectoryStructureHost) ||
                    ts.createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames);
                // Read updated contents from disk
                var configFileContent = ts.tryReadFile(configFilename, function (fileName) { return _this.host.readFile(fileName); });
                var configFile = ts.parseJsonText(configFilename, ts.isString(configFileContent) ? configFileContent : "");
                var configFileErrors = configFile.parseDiagnostics;
                if (!ts.isString(configFileContent))
                    configFileErrors.push(configFileContent);
                var parsedCommandLine = ts.parseJsonSourceFileConfigFileContent(configFile, cachedDirectoryStructureHost, ts.getDirectoryPath(configFilename), 
                /*existingOptions*/ {}, configFilename, 
                /*resolutionStack*/ [], this.hostConfiguration.extraFileExtensions, this.extendedConfigCache);
                if (parsedCommandLine.errors.length) {
                    configFileErrors.push.apply(configFileErrors, parsedCommandLine.errors);
                }
                this.logger.info("Config: ".concat(configFilename, " : ").concat(JSON.stringify({
                    rootNames: parsedCommandLine.fileNames,
                    options: parsedCommandLine.options,
                    watchOptions: parsedCommandLine.watchOptions,
                    projectReferences: parsedCommandLine.projectReferences
                }, /*replacer*/ undefined, " ")));
                var oldCommandLine = (_b = configFileExistenceInfo.config) === null || _b === void 0 ? void 0 : _b.parsedCommandLine;
                if (!configFileExistenceInfo.config) {
                    configFileExistenceInfo.config = { parsedCommandLine: parsedCommandLine, cachedDirectoryStructureHost: cachedDirectoryStructureHost, projects: new ts.Map() };
                }
                else {
                    configFileExistenceInfo.config.parsedCommandLine = parsedCommandLine;
                    configFileExistenceInfo.config.watchedDirectoriesStale = true;
                    configFileExistenceInfo.config.reloadLevel = undefined;
                }
                // If watch options different than older options when setting for the first time, update the config file watcher
                if (!oldCommandLine && !ts.isJsonEqual(
                // Old options
                this.getWatchOptionsFromProjectWatchOptions(/*projectOptions*/ undefined), 
                // New options
                this.getWatchOptionsFromProjectWatchOptions(parsedCommandLine.watchOptions))) {
                    // Reset the config file watcher
                    (_c = configFileExistenceInfo.watcher) === null || _c === void 0 ? void 0 : _c.close();
                    configFileExistenceInfo.watcher = undefined;
                }
                // Ensure there is watcher for this config file
                this.createConfigFileWatcherForParsedConfig(configFilename, canonicalConfigFilePath, forProject);
                // Watch extended config files
                ts.updateSharedExtendedConfigFileWatcher(canonicalConfigFilePath, parsedCommandLine.options, this.sharedExtendedConfigFileWatchers, function (extendedConfigFileName, extendedConfigFilePath) { return _this.watchFactory.watchFile(extendedConfigFileName, function () {
                    var _a;
                    // Update extended config cache
                    ts.cleanExtendedConfigCache(_this.extendedConfigCache, extendedConfigFilePath, function (fileName) { return _this.toPath(fileName); });
                    // Update projects
                    var ensureProjectsForOpenFiles = false;
                    (_a = _this.sharedExtendedConfigFileWatchers.get(extendedConfigFilePath)) === null || _a === void 0 ? void 0 : _a.projects.forEach(function (canonicalPath) {
                        ensureProjectsForOpenFiles = _this.delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalPath, "Change in extended config file ".concat(extendedConfigFileName, " detected")) || ensureProjectsForOpenFiles;
                    });
                    if (ensureProjectsForOpenFiles)
                        _this.delayEnsureProjectForOpenFiles();
                }, ts.PollingInterval.High, _this.hostConfiguration.watchOptions, ts.WatchType.ExtendedConfigFile, configFilename); }, function (fileName) { return _this.toPath(fileName); });
                return configFileExistenceInfo;
            };
            /*@internal*/
            ProjectService.prototype.watchWildcards = function (configFileName, _a, forProject) {
                var _this = this;
                var _b;
                var exists = _a.exists, config = _a.config;
                config.projects.set(forProject.canonicalConfigFilePath, true);
                if (exists) {
                    if (config.watchedDirectories && !config.watchedDirectoriesStale)
                        return;
                    config.watchedDirectoriesStale = false;
                    ts.updateWatchingWildcardDirectories((_b = config).watchedDirectories || (_b.watchedDirectories = new ts.Map()), new ts.Map(ts.getEntries(config.parsedCommandLine.wildcardDirectories)), 
                    // Create new directory watcher
                    function (directory, flags) { return _this.watchWildcardDirectory(directory, flags, configFileName, config); });
                }
                else {
                    config.watchedDirectoriesStale = false;
                    if (!config.watchedDirectories)
                        return;
                    ts.clearMap(config.watchedDirectories, ts.closeFileWatcherOf);
                    config.watchedDirectories = undefined;
                }
            };
            /*@internal*/
            ProjectService.prototype.stopWatchingWildCards = function (canonicalConfigFilePath, forProject) {
                var configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath);
                if (!configFileExistenceInfo.config ||
                    !configFileExistenceInfo.config.projects.get(forProject.canonicalConfigFilePath)) {
                    return;
                }
                configFileExistenceInfo.config.projects.set(forProject.canonicalConfigFilePath, false);
                // If any of the project is still watching wild cards dont close the watcher
                if (ts.forEachEntry(configFileExistenceInfo.config.projects, ts.identity))
                    return;
                if (configFileExistenceInfo.config.watchedDirectories) {
                    ts.clearMap(configFileExistenceInfo.config.watchedDirectories, ts.closeFileWatcherOf);
                    configFileExistenceInfo.config.watchedDirectories = undefined;
                }
                configFileExistenceInfo.config.watchedDirectoriesStale = undefined;
            };
            ProjectService.prototype.updateNonInferredProjectFiles = function (project, files, propertyReader) {
                var projectRootFilesMap = project.getRootFilesMap();
                var newRootScriptInfoMap = new ts.Map();
                for (var _i = 0, files_1 = files; _i < files_1.length; _i++) {
                    var f = files_1[_i];
                    var newRootFile = propertyReader.getFileName(f);
                    var fileName = server.toNormalizedPath(newRootFile);
                    var isDynamic = server.isDynamicFileName(fileName);
                    var path = void 0;
                    // Use the project's fileExists so that it can use caching instead of reaching to disk for the query
                    if (!isDynamic && !project.fileExists(newRootFile)) {
                        path = server.normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName);
                        var existingValue = projectRootFilesMap.get(path);
                        if (existingValue) {
                            if (existingValue.info) {
                                project.removeFile(existingValue.info, /*fileExists*/ false, /*detachFromProject*/ true);
                                existingValue.info = undefined;
                            }
                            existingValue.fileName = fileName;
                        }
                        else {
                            projectRootFilesMap.set(path, { fileName: fileName });
                        }
                    }
                    else {
                        var scriptKind = propertyReader.getScriptKind(f, this.hostConfiguration.extraFileExtensions);
                        var hasMixedContent = propertyReader.hasMixedContent(f, this.hostConfiguration.extraFileExtensions);
                        var scriptInfo = ts.Debug.checkDefined(this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(fileName, project.currentDirectory, scriptKind, hasMixedContent, project.directoryStructureHost));
                        path = scriptInfo.path;
                        var existingValue = projectRootFilesMap.get(path);
                        // If this script info is not already a root add it
                        if (!existingValue || existingValue.info !== scriptInfo) {
                            project.addRoot(scriptInfo, fileName);
                            if (scriptInfo.isScriptOpen()) {
                                // if file is already root in some inferred project
                                // - remove the file from that project and delete the project if necessary
                                this.removeRootOfInferredProjectIfNowPartOfOtherProject(scriptInfo);
                            }
                        }
                        else {
                            // Already root update the fileName
                            existingValue.fileName = fileName;
                        }
                    }
                    newRootScriptInfoMap.set(path, true);
                }
                // project's root file map size is always going to be same or larger than new roots map
                // as we have already all the new files to the project
                if (projectRootFilesMap.size > newRootScriptInfoMap.size) {
                    projectRootFilesMap.forEach(function (value, path) {
                        if (!newRootScriptInfoMap.has(path)) {
                            if (value.info) {
                                project.removeFile(value.info, project.fileExists(path), /*detachFromProject*/ true);
                            }
                            else {
                                projectRootFilesMap.delete(path);
                            }
                        }
                    });
                }
                // Just to ensure that even if root files dont change, the changes to the non root file are picked up,
                // mark the project as dirty unconditionally
                project.markAsDirty();
            };
            ProjectService.prototype.updateRootAndOptionsOfNonInferredProject = function (project, newUncheckedFiles, propertyReader, newOptions, newTypeAcquisition, compileOnSave, watchOptions) {
                project.setCompilerOptions(newOptions);
                project.setWatchOptions(watchOptions);
                // VS only set the CompileOnSaveEnabled option in the request if the option was changed recently
                // therefore if it is undefined, it should not be updated.
                if (compileOnSave !== undefined) {
                    project.compileOnSaveEnabled = compileOnSave;
                }
                this.addFilesToNonInferredProject(project, newUncheckedFiles, propertyReader, newTypeAcquisition);
            };
            /**
             * Reload the file names from config file specs and update the project graph
             */
            /*@internal*/
            ProjectService.prototype.reloadFileNamesOfConfiguredProject = function (project) {
                var fileNames = this.reloadFileNamesOfParsedConfig(project.getConfigFilePath(), this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath).config);
                project.updateErrorOnNoInputFiles(fileNames);
                this.updateNonInferredProjectFiles(project, fileNames.concat(project.getExternalFiles()), fileNamePropertyReader);
                return project.updateGraph();
            };
            /*@internal*/
            ProjectService.prototype.reloadFileNamesOfParsedConfig = function (configFileName, config) {
                if (config.reloadLevel === undefined)
                    return config.parsedCommandLine.fileNames;
                ts.Debug.assert(config.reloadLevel === ts.ConfigFileProgramReloadLevel.Partial);
                var configFileSpecs = config.parsedCommandLine.options.configFile.configFileSpecs;
                var fileNames = ts.getFileNamesFromConfigSpecs(configFileSpecs, ts.getDirectoryPath(configFileName), config.parsedCommandLine.options, config.cachedDirectoryStructureHost, this.hostConfiguration.extraFileExtensions);
                config.parsedCommandLine = __assign(__assign({}, config.parsedCommandLine), { fileNames: fileNames });
                return fileNames;
            };
            /*@internal*/
            ProjectService.prototype.setFileNamesOfAutoImportProviderProject = function (project, fileNames) {
                this.updateNonInferredProjectFiles(project, fileNames, fileNamePropertyReader);
            };
            /**
             * Read the config file of the project again by clearing the cache and update the project graph
             */
            /* @internal */
            ProjectService.prototype.reloadConfiguredProject = function (project, reason, isInitialLoad, clearSemanticCache) {
                // At this point, there is no reason to not have configFile in the host
                var host = project.getCachedDirectoryStructureHost();
                if (clearSemanticCache)
                    this.clearSemanticCache(project);
                // Clear the cache since we are reloading the project from disk
                host.clearCache();
                var configFileName = project.getConfigFilePath();
                this.logger.info("".concat(isInitialLoad ? "Loading" : "Reloading", " configured project ").concat(configFileName));
                // Load project from the disk
                this.loadConfiguredProject(project, reason);
                project.updateGraph();
                this.sendConfigFileDiagEvent(project, configFileName);
            };
            /* @internal */
            ProjectService.prototype.clearSemanticCache = function (project) {
                project.resolutionCache.clear();
                project.getLanguageService(/*ensureSynchronized*/ false).cleanupSemanticCache();
                project.markAsDirty();
            };
            ProjectService.prototype.sendConfigFileDiagEvent = function (project, triggerFile) {
                if (!this.eventHandler || this.suppressDiagnosticEvents) {
                    return;
                }
                var diagnostics = project.getLanguageService().getCompilerOptionsDiagnostics();
                diagnostics.push.apply(diagnostics, project.getAllProjectErrors());
                this.eventHandler({
                    eventName: server.ConfigFileDiagEvent,
                    data: { configFileName: project.getConfigFilePath(), diagnostics: diagnostics, triggerFile: triggerFile }
                });
            };
            ProjectService.prototype.getOrCreateInferredProjectForProjectRootPathIfEnabled = function (info, projectRootPath) {
                if (!this.useInferredProjectPerProjectRoot ||
                    // Its a dynamic info opened without project root
                    (info.isDynamic && projectRootPath === undefined)) {
                    return undefined;
                }
                if (projectRootPath) {
                    var canonicalProjectRootPath = this.toCanonicalFileName(projectRootPath);
                    // if we have an explicit project root path, find (or create) the matching inferred project.
                    for (var _i = 0, _a = this.inferredProjects; _i < _a.length; _i++) {
                        var project = _a[_i];
                        if (project.projectRootPath === canonicalProjectRootPath) {
                            return project;
                        }
                    }
                    return this.createInferredProject(projectRootPath, /*isSingleInferredProject*/ false, projectRootPath);
                }
                // we don't have an explicit root path, so we should try to find an inferred project
                // that more closely contains the file.
                var bestMatch;
                for (var _b = 0, _c = this.inferredProjects; _b < _c.length; _b++) {
                    var project = _c[_b];
                    // ignore single inferred projects (handled elsewhere)
                    if (!project.projectRootPath)
                        continue;
                    // ignore inferred projects that don't contain the root's path
                    if (!ts.containsPath(project.projectRootPath, info.path, this.host.getCurrentDirectory(), !this.host.useCaseSensitiveFileNames))
                        continue;
                    // ignore inferred projects that are higher up in the project root.
                    // TODO(rbuckton): Should we add the file as a root to these as well?
                    if (bestMatch && bestMatch.projectRootPath.length > project.projectRootPath.length)
                        continue;
                    bestMatch = project;
                }
                return bestMatch;
            };
            ProjectService.prototype.getOrCreateSingleInferredProjectIfEnabled = function () {
                if (!this.useSingleInferredProject) {
                    return undefined;
                }
                // If `useInferredProjectPerProjectRoot` is not enabled, then there will only be one
                // inferred project for all files. If `useInferredProjectPerProjectRoot` is enabled
                // then we want to put all files that are not opened with a `projectRootPath` into
                // the same inferred project.
                //
                // To avoid the cost of searching through the array and to optimize for the case where
                // `useInferredProjectPerProjectRoot` is not enabled, we will always put the inferred
                // project for non-rooted files at the front of the array.
                if (this.inferredProjects.length > 0 && this.inferredProjects[0].projectRootPath === undefined) {
                    return this.inferredProjects[0];
                }
                // Single inferred project does not have a project root and hence no current directory
                return this.createInferredProject(/*currentDirectory*/ undefined, /*isSingleInferredProject*/ true);
            };
            ProjectService.prototype.getOrCreateSingleInferredWithoutProjectRoot = function (currentDirectory) {
                ts.Debug.assert(!this.useSingleInferredProject);
                var expectedCurrentDirectory = this.toCanonicalFileName(this.getNormalizedAbsolutePath(currentDirectory || ""));
                // Reuse the project with same current directory but no roots
                for (var _i = 0, _a = this.inferredProjects; _i < _a.length; _i++) {
                    var inferredProject = _a[_i];
                    if (!inferredProject.projectRootPath &&
                        inferredProject.isOrphan() &&
                        inferredProject.canonicalCurrentDirectory === expectedCurrentDirectory) {
                        return inferredProject;
                    }
                }
                return this.createInferredProject(currentDirectory);
            };
            ProjectService.prototype.createInferredProject = function (currentDirectory, isSingleInferredProject, projectRootPath) {
                var compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects; // TODO: GH#18217
                var watchOptionsAndErrors;
                var typeAcquisition;
                if (projectRootPath) {
                    watchOptionsAndErrors = this.watchOptionsForInferredProjectsPerProjectRoot.get(projectRootPath);
                    typeAcquisition = this.typeAcquisitionForInferredProjectsPerProjectRoot.get(projectRootPath);
                }
                if (watchOptionsAndErrors === undefined) {
                    watchOptionsAndErrors = this.watchOptionsForInferredProjects;
                }
                if (typeAcquisition === undefined) {
                    typeAcquisition = this.typeAcquisitionForInferredProjects;
                }
                watchOptionsAndErrors = watchOptionsAndErrors || undefined;
                var project = new server.InferredProject(this, this.documentRegistry, compilerOptions, watchOptionsAndErrors === null || watchOptionsAndErrors === void 0 ? void 0 : watchOptionsAndErrors.watchOptions, projectRootPath, currentDirectory, this.currentPluginConfigOverrides, typeAcquisition);
                project.setProjectErrors(watchOptionsAndErrors === null || watchOptionsAndErrors === void 0 ? void 0 : watchOptionsAndErrors.errors);
                if (isSingleInferredProject) {
                    this.inferredProjects.unshift(project);
                }
                else {
                    this.inferredProjects.push(project);
                }
                return project;
            };
            /*@internal*/
            ProjectService.prototype.getOrCreateScriptInfoNotOpenedByClient = function (uncheckedFileName, currentDirectory, hostToQueryFileExistsOn) {
                return this.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath(server.toNormalizedPath(uncheckedFileName), currentDirectory, /*scriptKind*/ undefined, 
                /*hasMixedContent*/ undefined, hostToQueryFileExistsOn);
            };
            ProjectService.prototype.getScriptInfo = function (uncheckedFileName) {
                return this.getScriptInfoForNormalizedPath(server.toNormalizedPath(uncheckedFileName));
            };
            /* @internal */
            ProjectService.prototype.getScriptInfoOrConfig = function (uncheckedFileName) {
                var path = server.toNormalizedPath(uncheckedFileName);
                var info = this.getScriptInfoForNormalizedPath(path);
                if (info)
                    return info;
                var configProject = this.configuredProjects.get(this.toPath(uncheckedFileName));
                return configProject && configProject.getCompilerOptions().configFile;
            };
            /* @internal */
            ProjectService.prototype.logErrorForScriptInfoNotFound = function (fileName) {
                var names = ts.arrayFrom(this.filenameToScriptInfo.entries()).map(function (_a) {
                    var path = _a[0], scriptInfo = _a[1];
                    return ({ path: path, fileName: scriptInfo.fileName });
                });
                this.logger.msg("Could not find file ".concat(JSON.stringify(fileName), ".\nAll files are: ").concat(JSON.stringify(names)), server.Msg.Err);
            };
            /**
             * Returns the projects that contain script info through SymLink
             * Note that this does not return projects in info.containingProjects
             */
            /*@internal*/
            ProjectService.prototype.getSymlinkedProjects = function (info) {
                var projects;
                if (this.realpathToScriptInfos) {
                    var realpath = info.getRealpathIfDifferent();
                    if (realpath) {
                        ts.forEach(this.realpathToScriptInfos.get(realpath), combineProjects);
                    }
                    ts.forEach(this.realpathToScriptInfos.get(info.path), combineProjects);
                }
                return projects;
                function combineProjects(toAddInfo) {
                    if (toAddInfo !== info) {
                        var _loop_4 = function (project) {
                            // Add the projects only if they can use symLink targets and not already in the list
                            if (project.languageServiceEnabled &&
                                !project.isOrphan() &&
                                !project.getCompilerOptions().preserveSymlinks &&
                                !info.isAttached(project)) {
                                if (!projects) {
                                    projects = ts.createMultiMap();
                                    projects.add(toAddInfo.path, project);
                                }
                                else if (!ts.forEachEntry(projects, function (projs, path) { return path === toAddInfo.path ? false : ts.contains(projs, project); })) {
                                    projects.add(toAddInfo.path, project);
                                }
                            }
                        };
                        for (var _i = 0, _a = toAddInfo.containingProjects; _i < _a.length; _i++) {
                            var project = _a[_i];
                            _loop_4(project);
                        }
                    }
                }
            };
            ProjectService.prototype.watchClosedScriptInfo = function (info) {
                var _this = this;
                ts.Debug.assert(!info.fileWatcher);
                // do not watch files with mixed content - server doesn't know how to interpret it
                // do not watch files in the global cache location
                if (!info.isDynamicOrHasMixedContent() &&
                    (!this.globalCacheLocationDirectoryPath ||
                        !ts.startsWith(info.path, this.globalCacheLocationDirectoryPath))) {
                    var indexOfNodeModules = info.path.indexOf("/node_modules/");
                    if (!this.host.getModifiedTime || indexOfNodeModules === -1) {
                        info.fileWatcher = this.watchFactory.watchFile(info.fileName, function (_fileName, eventKind) { return _this.onSourceFileChanged(info, eventKind); }, ts.PollingInterval.Medium, this.hostConfiguration.watchOptions, ts.WatchType.ClosedScriptInfo);
                    }
                    else {
                        info.mTime = this.getModifiedTime(info);
                        info.fileWatcher = this.watchClosedScriptInfoInNodeModules(info.path.substr(0, indexOfNodeModules));
                    }
                }
            };
            ProjectService.prototype.createNodeModulesWatcher = function (dir) {
                var _this = this;
                var watcher = this.watchFactory.watchDirectory(dir, function (fileOrDirectory) {
                    var _a;
                    var fileOrDirectoryPath = ts.removeIgnoredPath(_this.toPath(fileOrDirectory));
                    if (!fileOrDirectoryPath)
                        return;
                    // Clear module specifier cache for any projects whose cache was affected by
                    // dependency package.jsons in this node_modules directory
                    var basename = ts.getBaseFileName(fileOrDirectoryPath);
                    if (((_a = result.affectedModuleSpecifierCacheProjects) === null || _a === void 0 ? void 0 : _a.size) && (basename === "package.json" || basename === "node_modules")) {
                        result.affectedModuleSpecifierCacheProjects.forEach(function (projectName) {
                            var _a, _b;
                            (_b = (_a = _this.findProject(projectName)) === null || _a === void 0 ? void 0 : _a.getModuleSpecifierCache()) === null || _b === void 0 ? void 0 : _b.clear();
                        });
                    }
                    // Refresh closed script info after an npm install
                    if (result.refreshScriptInfoRefCount) {
                        if (dir === fileOrDirectoryPath) {
                            _this.refreshScriptInfosInDirectory(dir);
                        }
                        else {
                            var info = _this.getScriptInfoForPath(fileOrDirectoryPath);
                            if (info) {
                                if (isScriptInfoWatchedFromNodeModules(info)) {
                                    _this.refreshScriptInfo(info);
                                }
                            }
                            // Folder
                            else if (!ts.hasExtension(fileOrDirectoryPath)) {
                                _this.refreshScriptInfosInDirectory(fileOrDirectoryPath);
                            }
                        }
                    }
                }, 1 /* WatchDirectoryFlags.Recursive */, this.hostConfiguration.watchOptions, ts.WatchType.NodeModules);
                var result = {
                    refreshScriptInfoRefCount: 0,
                    affectedModuleSpecifierCacheProjects: undefined,
                    close: function () {
                        var _a;
                        if (!result.refreshScriptInfoRefCount && !((_a = result.affectedModuleSpecifierCacheProjects) === null || _a === void 0 ? void 0 : _a.size)) {
                            watcher.close();
                            _this.nodeModulesWatchers.delete(dir);
                        }
                    },
                };
                this.nodeModulesWatchers.set(dir, result);
                return result;
            };
            /*@internal*/
            ProjectService.prototype.watchPackageJsonsInNodeModules = function (dir, project) {
                var watcher = this.nodeModulesWatchers.get(dir) || this.createNodeModulesWatcher(dir);
                (watcher.affectedModuleSpecifierCacheProjects || (watcher.affectedModuleSpecifierCacheProjects = new ts.Set())).add(project.getProjectName());
                return {
                    close: function () {
                        var _a;
                        (_a = watcher.affectedModuleSpecifierCacheProjects) === null || _a === void 0 ? void 0 : _a.delete(project.getProjectName());
                        watcher.close();
                    },
                };
            };
            ProjectService.prototype.watchClosedScriptInfoInNodeModules = function (dir) {
                var watchDir = dir + "/node_modules";
                var watcher = this.nodeModulesWatchers.get(watchDir) || this.createNodeModulesWatcher(watchDir);
                watcher.refreshScriptInfoRefCount++;
                return {
                    close: function () {
                        watcher.refreshScriptInfoRefCount--;
                        watcher.close();
                    },
                };
            };
            ProjectService.prototype.getModifiedTime = function (info) {
                return (this.host.getModifiedTime(info.path) || ts.missingFileModifiedTime).getTime();
            };
            ProjectService.prototype.refreshScriptInfo = function (info) {
                var mTime = this.getModifiedTime(info);
                if (mTime !== info.mTime) {
                    var eventKind = ts.getFileWatcherEventKind(info.mTime, mTime);
                    info.mTime = mTime;
                    this.onSourceFileChanged(info, eventKind);
                }
            };
            ProjectService.prototype.refreshScriptInfosInDirectory = function (dir) {
                var _this = this;
                dir = dir + ts.directorySeparator;
                this.filenameToScriptInfo.forEach(function (info) {
                    if (isScriptInfoWatchedFromNodeModules(info) && ts.startsWith(info.path, dir)) {
                        _this.refreshScriptInfo(info);
                    }
                });
            };
            ProjectService.prototype.stopWatchingScriptInfo = function (info) {
                if (info.fileWatcher) {
                    info.fileWatcher.close();
                    info.fileWatcher = undefined;
                }
            };
            ProjectService.prototype.getOrCreateScriptInfoNotOpenedByClientForNormalizedPath = function (fileName, currentDirectory, scriptKind, hasMixedContent, hostToQueryFileExistsOn) {
                if (ts.isRootedDiskPath(fileName) || server.isDynamicFileName(fileName)) {
                    return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ false, /*fileContent*/ undefined, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
                }
                // This is non rooted path with different current directory than project service current directory
                // Only paths recognized are open relative file paths
                var info = this.openFilesWithNonRootedDiskPath.get(this.toCanonicalFileName(fileName));
                if (info) {
                    return info;
                }
                // This means triple slash references wont be resolved in dynamic and unsaved files
                // which is intentional since we dont know what it means to be relative to non disk files
                return undefined;
            };
            ProjectService.prototype.getOrCreateScriptInfoOpenedByClientForNormalizedPath = function (fileName, currentDirectory, fileContent, scriptKind, hasMixedContent) {
                return this.getOrCreateScriptInfoWorker(fileName, currentDirectory, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent);
            };
            ProjectService.prototype.getOrCreateScriptInfoForNormalizedPath = function (fileName, openedByClient, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn) {
                return this.getOrCreateScriptInfoWorker(fileName, this.currentDirectory, openedByClient, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn);
            };
            ProjectService.prototype.getOrCreateScriptInfoWorker = function (fileName, currentDirectory, openedByClient, fileContent, scriptKind, hasMixedContent, hostToQueryFileExistsOn) {
                var _this = this;
                ts.Debug.assert(fileContent === undefined || openedByClient, "ScriptInfo needs to be opened by client to be able to set its user defined content");
                var path = server.normalizedPathToPath(fileName, currentDirectory, this.toCanonicalFileName);
                var info = this.getScriptInfoForPath(path);
                if (!info) {
                    var isDynamic = server.isDynamicFileName(fileName);
                    ts.Debug.assert(ts.isRootedDiskPath(fileName) || isDynamic || openedByClient, "", function () { return "".concat(JSON.stringify({ fileName: fileName, currentDirectory: currentDirectory, hostCurrentDirectory: _this.currentDirectory, openKeys: ts.arrayFrom(_this.openFilesWithNonRootedDiskPath.keys()) }), "\nScript info with non-dynamic relative file name can only be open script info or in context of host currentDirectory"); });
                    ts.Debug.assert(!ts.isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "", function () { return "".concat(JSON.stringify({ fileName: fileName, currentDirectory: currentDirectory, hostCurrentDirectory: _this.currentDirectory, openKeys: ts.arrayFrom(_this.openFilesWithNonRootedDiskPath.keys()) }), "\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names"); });
                    ts.Debug.assert(!isDynamic || this.currentDirectory === currentDirectory || this.useInferredProjectPerProjectRoot, "", function () { return "".concat(JSON.stringify({ fileName: fileName, currentDirectory: currentDirectory, hostCurrentDirectory: _this.currentDirectory, openKeys: ts.arrayFrom(_this.openFilesWithNonRootedDiskPath.keys()) }), "\nDynamic files must always be opened with service's current directory or service should support inferred project per projectRootPath."); });
                    // If the file is not opened by client and the file doesnot exist on the disk, return
                    if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) {
                        return;
                    }
                    info = new server.ScriptInfo(this.host, fileName, scriptKind, !!hasMixedContent, path, this.filenameToScriptInfoVersion.get(path)); // TODO: GH#18217
                    this.filenameToScriptInfo.set(info.path, info);
                    this.filenameToScriptInfoVersion.delete(info.path);
                    if (!openedByClient) {
                        this.watchClosedScriptInfo(info);
                    }
                    else if (!ts.isRootedDiskPath(fileName) && (!isDynamic || this.currentDirectory !== currentDirectory)) {
                        // File that is opened by user but isn't rooted disk path
                        this.openFilesWithNonRootedDiskPath.set(this.toCanonicalFileName(fileName), info);
                    }
                }
                if (openedByClient) {
                    // Opening closed script info
                    // either it was created just now, or was part of projects but was closed
                    this.stopWatchingScriptInfo(info);
                    info.open(fileContent);
                    if (hasMixedContent) {
                        info.registerFileUpdate();
                    }
                }
                return info;
            };
            /**
             * This gets the script info for the normalized path. If the path is not rooted disk path then the open script info with project root context is preferred
             */
            ProjectService.prototype.getScriptInfoForNormalizedPath = function (fileName) {
                return !ts.isRootedDiskPath(fileName) && this.openFilesWithNonRootedDiskPath.get(this.toCanonicalFileName(fileName)) ||
                    this.getScriptInfoForPath(server.normalizedPathToPath(fileName, this.currentDirectory, this.toCanonicalFileName));
            };
            ProjectService.prototype.getScriptInfoForPath = function (fileName) {
                return this.filenameToScriptInfo.get(fileName);
            };
            /*@internal*/
            ProjectService.prototype.getDocumentPositionMapper = function (project, generatedFileName, sourceFileName) {
                var _this = this;
                // Since declaration info and map file watches arent updating project's directory structure host (which can cache file structure) use host
                var declarationInfo = this.getOrCreateScriptInfoNotOpenedByClient(generatedFileName, project.currentDirectory, this.host);
                if (!declarationInfo) {
                    if (sourceFileName) {
                        // Project contains source file and it generates the generated file name
                        project.addGeneratedFileWatch(generatedFileName, sourceFileName);
                    }
                    return undefined;
                }
                // Try to get from cache
                declarationInfo.getSnapshot(); // Ensure synchronized
                if (ts.isString(declarationInfo.sourceMapFilePath)) {
                    // Ensure mapper is synchronized
                    var sourceMapFileInfo_1 = this.getScriptInfoForPath(declarationInfo.sourceMapFilePath);
                    if (sourceMapFileInfo_1) {
                        sourceMapFileInfo_1.getSnapshot();
                        if (sourceMapFileInfo_1.documentPositionMapper !== undefined) {
                            sourceMapFileInfo_1.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, sourceMapFileInfo_1.sourceInfos);
                            return sourceMapFileInfo_1.documentPositionMapper ? sourceMapFileInfo_1.documentPositionMapper : undefined;
                        }
                    }
                    declarationInfo.sourceMapFilePath = undefined;
                }
                else if (declarationInfo.sourceMapFilePath) {
                    declarationInfo.sourceMapFilePath.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, declarationInfo.sourceMapFilePath.sourceInfos);
                    return undefined;
                }
                else if (declarationInfo.sourceMapFilePath !== undefined) {
                    // Doesnt have sourceMap
                    return undefined;
                }
                // Create the mapper
                var sourceMapFileInfo;
                var mapFileNameFromDeclarationInfo;
                var readMapFile = function (mapFileName, mapFileNameFromDts) {
                    var mapInfo = _this.getOrCreateScriptInfoNotOpenedByClient(mapFileName, project.currentDirectory, _this.host);
                    if (!mapInfo) {
                        mapFileNameFromDeclarationInfo = mapFileNameFromDts;
                        return undefined;
                    }
                    sourceMapFileInfo = mapInfo;
                    var snap = mapInfo.getSnapshot();
                    if (mapInfo.documentPositionMapper !== undefined)
                        return mapInfo.documentPositionMapper;
                    return ts.getSnapshotText(snap);
                };
                var projectName = project.projectName;
                var documentPositionMapper = ts.getDocumentPositionMapper({ getCanonicalFileName: this.toCanonicalFileName, log: function (s) { return _this.logger.info(s); }, getSourceFileLike: function (f) { return _this.getSourceFileLike(f, projectName, declarationInfo); } }, declarationInfo.fileName, declarationInfo.getLineInfo(), readMapFile);
                readMapFile = undefined; // Remove ref to project
                if (sourceMapFileInfo) {
                    declarationInfo.sourceMapFilePath = sourceMapFileInfo.path;
                    sourceMapFileInfo.declarationInfoPath = declarationInfo.path;
                    sourceMapFileInfo.documentPositionMapper = documentPositionMapper || false;
                    sourceMapFileInfo.sourceInfos = this.addSourceInfoToSourceMap(sourceFileName, project, sourceMapFileInfo.sourceInfos);
                }
                else if (mapFileNameFromDeclarationInfo) {
                    declarationInfo.sourceMapFilePath = {
                        watcher: this.addMissingSourceMapFile(project.currentDirectory === this.currentDirectory ?
                            mapFileNameFromDeclarationInfo :
                            ts.getNormalizedAbsolutePath(mapFileNameFromDeclarationInfo, project.currentDirectory), declarationInfo.path),
                        sourceInfos: this.addSourceInfoToSourceMap(sourceFileName, project)
                    };
                }
                else {
                    declarationInfo.sourceMapFilePath = false;
                }
                return documentPositionMapper;
            };
            ProjectService.prototype.addSourceInfoToSourceMap = function (sourceFileName, project, sourceInfos) {
                if (sourceFileName) {
                    // Attach as source
                    var sourceInfo = this.getOrCreateScriptInfoNotOpenedByClient(sourceFileName, project.currentDirectory, project.directoryStructureHost);
                    (sourceInfos || (sourceInfos = new ts.Set())).add(sourceInfo.path);
                }
                return sourceInfos;
            };
            ProjectService.prototype.addMissingSourceMapFile = function (mapFileName, declarationInfoPath) {
                var _this = this;
                var fileWatcher = this.watchFactory.watchFile(mapFileName, function () {
                    var declarationInfo = _this.getScriptInfoForPath(declarationInfoPath);
                    if (declarationInfo && declarationInfo.sourceMapFilePath && !ts.isString(declarationInfo.sourceMapFilePath)) {
                        // Update declaration and source projects
                        _this.delayUpdateProjectGraphs(declarationInfo.containingProjects, /*clearSourceMapperCache*/ true);
                        _this.delayUpdateSourceInfoProjects(declarationInfo.sourceMapFilePath.sourceInfos);
                        declarationInfo.closeSourceMapFileWatcher();
                    }
                }, ts.PollingInterval.High, this.hostConfiguration.watchOptions, ts.WatchType.MissingSourceMapFile);
                return fileWatcher;
            };
            /*@internal*/
            ProjectService.prototype.getSourceFileLike = function (fileName, projectNameOrProject, declarationInfo) {
                var project = projectNameOrProject.projectName ? projectNameOrProject : this.findProject(projectNameOrProject);
                if (project) {
                    var path = project.toPath(fileName);
                    var sourceFile = project.getSourceFile(path);
                    if (sourceFile && sourceFile.resolvedPath === path)
                        return sourceFile;
                }
                // Need to look for other files.
                var info = this.getOrCreateScriptInfoNotOpenedByClient(fileName, (project || this).currentDirectory, project ? project.directoryStructureHost : this.host);
                if (!info)
                    return undefined;
                // Attach as source
                if (declarationInfo && ts.isString(declarationInfo.sourceMapFilePath) && info !== declarationInfo) {
                    var sourceMapInfo = this.getScriptInfoForPath(declarationInfo.sourceMapFilePath);
                    if (sourceMapInfo) {
                        (sourceMapInfo.sourceInfos || (sourceMapInfo.sourceInfos = new ts.Set())).add(info.path);
                    }
                }
                // Key doesnt matter since its only for text and lines
                if (info.cacheSourceFile)
                    return info.cacheSourceFile.sourceFile;
                // Create sourceFileLike
                if (!info.sourceFileLike) {
                    info.sourceFileLike = {
                        get text() {
                            ts.Debug.fail("shouldnt need text");
                            return "";
                        },
                        getLineAndCharacterOfPosition: function (pos) {
                            var lineOffset = info.positionToLineOffset(pos);
                            return { line: lineOffset.line - 1, character: lineOffset.offset - 1 };
                        },
                        getPositionOfLineAndCharacter: function (line, character, allowEdits) { return info.lineOffsetToPosition(line + 1, character + 1, allowEdits); }
                    };
                }
                return info.sourceFileLike;
            };
            /*@internal*/
            ProjectService.prototype.setPerformanceEventHandler = function (performanceEventHandler) {
                this.performanceEventHandler = performanceEventHandler;
            };
            ProjectService.prototype.setHostConfiguration = function (args) {
                var _this = this;
                var _a;
                if (args.file) {
                    var info = this.getScriptInfoForNormalizedPath(server.toNormalizedPath(args.file));
                    if (info) {
                        info.setOptions(convertFormatOptions(args.formatOptions), args.preferences);
                        this.logger.info("Host configuration update for file ".concat(args.file));
                    }
                }
                else {
                    if (args.hostInfo !== undefined) {
                        this.hostConfiguration.hostInfo = args.hostInfo;
                        this.logger.info("Host information ".concat(args.hostInfo));
                    }
                    if (args.formatOptions) {
                        this.hostConfiguration.formatCodeOptions = __assign(__assign({}, this.hostConfiguration.formatCodeOptions), convertFormatOptions(args.formatOptions));
                        this.logger.info("Format host information updated");
                    }
                    if (args.preferences) {
                        var _b = this.hostConfiguration.preferences, lazyConfiguredProjectsFromExternalProject = _b.lazyConfiguredProjectsFromExternalProject, includePackageJsonAutoImports = _b.includePackageJsonAutoImports;
                        this.hostConfiguration.preferences = __assign(__assign({}, this.hostConfiguration.preferences), args.preferences);
                        if (lazyConfiguredProjectsFromExternalProject && !this.hostConfiguration.preferences.lazyConfiguredProjectsFromExternalProject) {
                            // Load configured projects for external projects that are pending reload
                            this.configuredProjects.forEach(function (project) {
                                if (project.hasExternalProjectRef() &&
                                    project.pendingReload === ts.ConfigFileProgramReloadLevel.Full &&
                                    !_this.pendingProjectUpdates.has(project.getProjectName())) {
                                    project.updateGraph();
                                }
                            });
                        }
                        if (includePackageJsonAutoImports !== args.preferences.includePackageJsonAutoImports) {
                            this.invalidateProjectPackageJson(/*packageJsonPath*/ undefined);
                        }
                    }
                    if (args.extraFileExtensions) {
                        this.hostConfiguration.extraFileExtensions = args.extraFileExtensions;
                        // We need to update the project structures again as it is possible that existing
                        // project structure could have more or less files depending on extensions permitted
                        this.reloadProjects();
                        this.logger.info("Host file extension mappings updated");
                    }
                    if (args.watchOptions) {
                        this.hostConfiguration.watchOptions = (_a = convertWatchOptions(args.watchOptions)) === null || _a === void 0 ? void 0 : _a.watchOptions;
                        this.logger.info("Host watch options changed to ".concat(JSON.stringify(this.hostConfiguration.watchOptions), ", it will be take effect for next watches."));
                    }
                }
            };
            /*@internal*/
            ProjectService.prototype.getWatchOptions = function (project) {
                return this.getWatchOptionsFromProjectWatchOptions(project.getWatchOptions());
            };
            /*@internal*/
            ProjectService.prototype.getWatchOptionsFromProjectWatchOptions = function (projectOptions) {
                return projectOptions && this.hostConfiguration.watchOptions ? __assign(__assign({}, this.hostConfiguration.watchOptions), projectOptions) :
                    projectOptions || this.hostConfiguration.watchOptions;
            };
            ProjectService.prototype.closeLog = function () {
                this.logger.close();
            };
            /**
             * This function rebuilds the project for every file opened by the client
             * This does not reload contents of open files from disk. But we could do that if needed
             */
            ProjectService.prototype.reloadProjects = function () {
                var _this = this;
                this.logger.info("reload projects.");
                // If we want this to also reload open files from disk, we could do that,
                // but then we need to make sure we arent calling this function
                // (and would separate out below reloading of projects to be called when immediate reload is needed)
                // as there is no need to load contents of the files from the disk
                // Reload script infos
                this.filenameToScriptInfo.forEach(function (info) {
                    if (_this.openFiles.has(info.path))
                        return; // Skip open files
                    if (!info.fileWatcher)
                        return; // not watched file
                    // Handle as if file is changed or deleted
                    _this.onSourceFileChanged(info, _this.host.fileExists(info.fileName) ? ts.FileWatcherEventKind.Changed : ts.FileWatcherEventKind.Deleted);
                });
                // Cancel all project updates since we will be updating them now
                this.pendingProjectUpdates.forEach(function (_project, projectName) {
                    _this.throttledOperations.cancel(projectName);
                    _this.pendingProjectUpdates.delete(projectName);
                });
                this.throttledOperations.cancel(ensureProjectForOpenFileSchedule);
                this.pendingEnsureProjectForOpenFiles = false;
                // Ensure everything is reloaded for cached configs
                this.configFileExistenceInfoCache.forEach(function (info) {
                    if (info.config)
                        info.config.reloadLevel = ts.ConfigFileProgramReloadLevel.Full;
                });
                // Reload Projects
                this.reloadConfiguredProjectForFiles(this.openFiles, /*clearSemanticCache*/ true, /*delayReload*/ false, ts.returnTrue, "User requested reload projects");
                this.externalProjects.forEach(function (project) {
                    _this.clearSemanticCache(project);
                    project.updateGraph();
                });
                this.inferredProjects.forEach(function (project) { return _this.clearSemanticCache(project); });
                this.ensureProjectForOpenFiles();
            };
            /**
             * This function goes through all the openFiles and tries to file the config file for them.
             * If the config file is found and it refers to existing project, it reloads it either immediately
             * or schedules it for reload depending on delayReload option
             * If there is no existing project it just opens the configured project for the config file
             * reloadForInfo provides a way to filter out files to reload configured project for
             */
            ProjectService.prototype.reloadConfiguredProjectForFiles = function (openFiles, clearSemanticCache, delayReload, shouldReloadProjectFor, reason) {
                var _this = this;
                var updatedProjects = new ts.Map();
                var reloadChildProject = function (child) {
                    if (!updatedProjects.has(child.canonicalConfigFilePath)) {
                        updatedProjects.set(child.canonicalConfigFilePath, true);
                        _this.reloadConfiguredProject(child, reason, /*isInitialLoad*/ false, clearSemanticCache);
                    }
                };
                // try to reload config file for all open files
                openFiles === null || openFiles === void 0 ? void 0 : openFiles.forEach(function (openFileValue, path) {
                    // Invalidate default config file name for open file
                    _this.configFileForOpenFiles.delete(path);
                    // Filter out the files that need to be ignored
                    if (!shouldReloadProjectFor(openFileValue)) {
                        return;
                    }
                    var info = _this.getScriptInfoForPath(path); // TODO: GH#18217
                    ts.Debug.assert(info.isScriptOpen());
                    // This tries to search for a tsconfig.json for the given file. If we found it,
                    // we first detect if there is already a configured project created for it: if so,
                    // we re- read the tsconfig file content and update the project only if we havent already done so
                    // otherwise we create a new one.
                    var configFileName = _this.getConfigFileNameForFile(info);
                    if (configFileName) {
                        var project = _this.findConfiguredProjectByProjectName(configFileName) || _this.createConfiguredProject(configFileName);
                        if (!updatedProjects.has(project.canonicalConfigFilePath)) {
                            updatedProjects.set(project.canonicalConfigFilePath, true);
                            if (delayReload) {
                                project.pendingReload = ts.ConfigFileProgramReloadLevel.Full;
                                project.pendingReloadReason = reason;
                                if (clearSemanticCache)
                                    _this.clearSemanticCache(project);
                                _this.delayUpdateProjectGraph(project);
                            }
                            else {
                                // reload from the disk
                                _this.reloadConfiguredProject(project, reason, /*isInitialLoad*/ false, clearSemanticCache);
                                // If this project does not contain this file directly, reload the project till the reloaded project contains the script info directly
                                if (!projectContainsInfoDirectly(project, info)) {
                                    var referencedProject = forEachResolvedProjectReferenceProject(project, info.path, function (child) {
                                        reloadChildProject(child);
                                        return projectContainsInfoDirectly(child, info);
                                    }, ProjectReferenceProjectLoadKind.FindCreate);
                                    if (referencedProject) {
                                        // Reload the project's tree that is already present
                                        forEachResolvedProjectReferenceProject(project, 
                                        /*fileName*/ undefined, reloadChildProject, ProjectReferenceProjectLoadKind.Find);
                                    }
                                }
                            }
                        }
                    }
                });
            };
            /**
             * Remove the root of inferred project if script info is part of another project
             */
            ProjectService.prototype.removeRootOfInferredProjectIfNowPartOfOtherProject = function (info) {
                // If the script info is root of inferred project, it could only be first containing project
                // since info is added as root to the inferred project only when there are no other projects containing it
                // So when it is root of the inferred project and after project structure updates its now part
                // of multiple project it needs to be removed from that inferred project because:
                // - references in inferred project supersede the root part
                // - root / reference in non - inferred project beats root in inferred project
                // eg. say this is structure /a/b/a.ts /a/b/c.ts where c.ts references a.ts
                // When a.ts is opened, since there is no configured project/external project a.ts can be part of
                // a.ts is added as root to inferred project.
                // Now at time of opening c.ts, c.ts is also not aprt of any existing project,
                // so it will be added to inferred project as a root. (for sake of this example assume single inferred project is false)
                // So at this poing a.ts is part of first inferred project and second inferred project (of which c.ts is root)
                // And hence it needs to be removed from the first inferred project.
                ts.Debug.assert(info.containingProjects.length > 0);
                var firstProject = info.containingProjects[0];
                if (!firstProject.isOrphan() &&
                    server.isInferredProject(firstProject) &&
                    firstProject.isRoot(info) &&
                    ts.forEach(info.containingProjects, function (p) { return p !== firstProject && !p.isOrphan(); })) {
                    firstProject.removeFile(info, /*fileExists*/ true, /*detachFromProject*/ true);
                }
            };
            /**
             * This function is to update the project structure for every inferred project.
             * It is called on the premise that all the configured projects are
             * up to date.
             * This will go through open files and assign them to inferred project if open file is not part of any other project
             * After that all the inferred project graphs are updated
             */
            ProjectService.prototype.ensureProjectForOpenFiles = function () {
                var _this = this;
                this.logger.info("Before ensureProjectForOpenFiles:");
                this.printProjects();
                this.openFiles.forEach(function (projectRootPath, path) {
                    var info = _this.getScriptInfoForPath(path);
                    // collect all orphaned script infos from open files
                    if (info.isOrphan()) {
                        _this.assignOrphanScriptInfoToInferredProject(info, projectRootPath);
                    }
                    else {
                        // Or remove the root of inferred project if is referenced in more than one projects
                        _this.removeRootOfInferredProjectIfNowPartOfOtherProject(info);
                    }
                });
                this.pendingEnsureProjectForOpenFiles = false;
                this.inferredProjects.forEach(updateProjectIfDirty);
                this.logger.info("After ensureProjectForOpenFiles:");
                this.printProjects();
            };
            /**
             * Open file whose contents is managed by the client
             * @param filename is absolute pathname
             * @param fileContent is a known version of the file content that is more up to date than the one on disk
             */
            ProjectService.prototype.openClientFile = function (fileName, fileContent, scriptKind, projectRootPath) {
                return this.openClientFileWithNormalizedPath(server.toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? server.toNormalizedPath(projectRootPath) : undefined);
            };
            /*@internal*/
            ProjectService.prototype.getOriginalLocationEnsuringConfiguredProject = function (project, location) {
                var _this = this;
                var isSourceOfProjectReferenceRedirect = project.isSourceOfProjectReferenceRedirect(location.fileName);
                var originalLocation = isSourceOfProjectReferenceRedirect ?
                    location :
                    project.getSourceMapper().tryGetSourcePosition(location);
                if (!originalLocation)
                    return undefined;
                var fileName = originalLocation.fileName;
                var scriptInfo = this.getScriptInfo(fileName);
                if (!scriptInfo && !this.host.fileExists(fileName))
                    return undefined;
                var originalFileInfo = { fileName: server.toNormalizedPath(fileName), path: this.toPath(fileName) };
                var configFileName = this.getConfigFileNameForFile(originalFileInfo);
                if (!configFileName)
                    return undefined;
                var configuredProject = this.findConfiguredProjectByProjectName(configFileName);
                if (!configuredProject) {
                    if (project.getCompilerOptions().disableReferencedProjectLoad) {
                        // If location was a project reference redirect, then `location` and `originalLocation` are the same.
                        if (isSourceOfProjectReferenceRedirect) {
                            return location;
                        }
                        // Otherwise, if we found `originalLocation` via a source map instead, then we check whether it's in
                        // an open project.  If it is, we should search the containing project(s), even though the "default"
                        // configured project isn't open.  However, if it's not in an open project, we need to stick with
                        // `location` (i.e. the .d.ts file) because otherwise we'll miss the references in that file.
                        return (scriptInfo === null || scriptInfo === void 0 ? void 0 : scriptInfo.containingProjects.length)
                            ? originalLocation
                            : location;
                    }
                    configuredProject = this.createAndLoadConfiguredProject(configFileName, "Creating project for original file: ".concat(originalFileInfo.fileName).concat(location !== originalLocation ? " for location: " + location.fileName : ""));
                }
                updateProjectIfDirty(configuredProject);
                var projectContainsOriginalInfo = function (project) {
                    var info = _this.getScriptInfo(fileName);
                    return info && projectContainsInfoDirectly(project, info);
                };
                if (configuredProject.isSolution() || !projectContainsOriginalInfo(configuredProject)) {
                    // Find the project that is referenced from this solution that contains the script info directly
                    configuredProject = forEachResolvedProjectReferenceProject(configuredProject, fileName, function (child) {
                        updateProjectIfDirty(child);
                        return projectContainsOriginalInfo(child) ? child : undefined;
                    }, ProjectReferenceProjectLoadKind.FindCreateLoad, "Creating project referenced in solution ".concat(configuredProject.projectName, " to find possible configured project for original file: ").concat(originalFileInfo.fileName).concat(location !== originalLocation ? " for location: " + location.fileName : ""));
                    if (!configuredProject)
                        return undefined;
                    if (configuredProject === project)
                        return originalLocation;
                }
                // Keep this configured project as referenced from project
                addOriginalConfiguredProject(configuredProject);
                var originalScriptInfo = this.getScriptInfo(fileName);
                if (!originalScriptInfo || !originalScriptInfo.containingProjects.length)
                    return undefined;
                // Add configured projects as referenced
                originalScriptInfo.containingProjects.forEach(function (project) {
                    if (server.isConfiguredProject(project)) {
                        addOriginalConfiguredProject(project);
                    }
                });
                return originalLocation;
                function addOriginalConfiguredProject(originalProject) {
                    if (!project.originalConfiguredProjects) {
                        project.originalConfiguredProjects = new ts.Set();
                    }
                    project.originalConfiguredProjects.add(originalProject.canonicalConfigFilePath);
                }
            };
            /** @internal */
            ProjectService.prototype.fileExists = function (fileName) {
                return !!this.getScriptInfoForNormalizedPath(fileName) || this.host.fileExists(fileName);
            };
            ProjectService.prototype.findExternalProjectContainingOpenScriptInfo = function (info) {
                return ts.find(this.externalProjects, function (proj) {
                    // Ensure project structure is up-to-date to check if info is present in external project
                    updateProjectIfDirty(proj);
                    return proj.containsScriptInfo(info);
                });
            };
            ProjectService.prototype.getOrCreateOpenScriptInfo = function (fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) {
                var info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent); // TODO: GH#18217
                this.openFiles.set(info.path, projectRootPath);
                return info;
            };
            ProjectService.prototype.assignProjectToOpenedScriptInfo = function (info) {
                var _this = this;
                var configFileName;
                var configFileErrors;
                var project = this.findExternalProjectContainingOpenScriptInfo(info);
                var retainProjects;
                var projectForConfigFileDiag;
                var defaultConfigProjectIsCreated = false;
                if (!project && this.serverMode === ts.LanguageServiceMode.Semantic) { // Checking semantic mode is an optimization
                    configFileName = this.getConfigFileNameForFile(info);
                    if (configFileName) {
                        project = this.findConfiguredProjectByProjectName(configFileName);
                        if (!project) {
                            project = this.createLoadAndUpdateConfiguredProject(configFileName, "Creating possible configured project for ".concat(info.fileName, " to open"));
                            defaultConfigProjectIsCreated = true;
                        }
                        else {
                            // Ensure project is ready to check if it contains opened script info
                            updateProjectIfDirty(project);
                        }
                        projectForConfigFileDiag = project.containsScriptInfo(info) ? project : undefined;
                        retainProjects = project;
                        // If this configured project doesnt contain script info but
                        // it is solution with project references, try those project references
                        if (!projectContainsInfoDirectly(project, info)) {
                            forEachResolvedProjectReferenceProject(project, info.path, function (child) {
                                updateProjectIfDirty(child);
                                // Retain these projects
                                if (!ts.isArray(retainProjects)) {
                                    retainProjects = [project, child];
                                }
                                else {
                                    retainProjects.push(child);
                                }
                                // If script info belongs to this child project, use this as default config project
                                if (projectContainsInfoDirectly(child, info)) {
                                    projectForConfigFileDiag = child;
                                    return child;
                                }
                                // If this project uses the script info (even through project reference), if default project is not found, use this for configFileDiag
                                if (!projectForConfigFileDiag && child.containsScriptInfo(info)) {
                                    projectForConfigFileDiag = child;
                                }
                            }, ProjectReferenceProjectLoadKind.FindCreateLoad, "Creating project referenced in solution ".concat(project.projectName, " to find possible configured project for ").concat(info.fileName, " to open"));
                        }
                        // Send the event only if the project got created as part of this open request and info is part of the project
                        if (projectForConfigFileDiag) {
                            configFileName = projectForConfigFileDiag.getConfigFilePath();
                            if (projectForConfigFileDiag !== project || defaultConfigProjectIsCreated) {
                                configFileErrors = projectForConfigFileDiag.getAllProjectErrors();
                                this.sendConfigFileDiagEvent(projectForConfigFileDiag, info.fileName);
                            }
                        }
                        else {
                            // Since the file isnt part of configured project, do not send config file info
                            configFileName = undefined;
                        }
                        // Create ancestor configured project
                        this.createAncestorProjects(info, project);
                    }
                }
                // Project we have at this point is going to be updated since its either found through
                // - external project search, which updates the project before checking if info is present in it
                // - configured project - either created or updated to ensure we know correct status of info
                // At this point we need to ensure that containing projects of the info are uptodate
                // This will ensure that later question of info.isOrphan() will return correct answer
                // and we correctly create inferred project for the info
                info.containingProjects.forEach(updateProjectIfDirty);
                // At this point if file is part of any any configured or external project, then it would be present in the containing projects
                // So if it still doesnt have any containing projects, it needs to be part of inferred project
                if (info.isOrphan()) {
                    // Even though this info did not belong to any of the configured projects, send the config file diag
                    if (ts.isArray(retainProjects)) {
                        retainProjects.forEach(function (project) { return _this.sendConfigFileDiagEvent(project, info.fileName); });
                    }
                    else if (retainProjects) {
                        this.sendConfigFileDiagEvent(retainProjects, info.fileName);
                    }
                    ts.Debug.assert(this.openFiles.has(info.path));
                    this.assignOrphanScriptInfoToInferredProject(info, this.openFiles.get(info.path));
                }
                ts.Debug.assert(!info.isOrphan());
                return { configFileName: configFileName, configFileErrors: configFileErrors, retainProjects: retainProjects };
            };
            ProjectService.prototype.createAncestorProjects = function (info, project) {
                // Skip if info is not part of default configured project
                if (!info.isAttached(project))
                    return;
                // Create configured project till project root
                while (true) {
                    // Skip if project is not composite
                    if (!project.isInitialLoadPending() &&
                        (!project.getCompilerOptions().composite ||
                            project.getCompilerOptions().disableSolutionSearching))
                        return;
                    // Get config file name
                    var configFileName = this.getConfigFileNameForFile({
                        fileName: project.getConfigFilePath(),
                        path: info.path,
                        configFileInfo: true
                    });
                    if (!configFileName)
                        return;
                    // find or delay load the project
                    var ancestor = this.findConfiguredProjectByProjectName(configFileName) ||
                        this.createConfiguredProjectWithDelayLoad(configFileName, "Creating project possibly referencing default composite project ".concat(project.getProjectName(), " of open file ").concat(info.fileName));
                    if (ancestor.isInitialLoadPending()) {
                        // Set a potential project reference
                        ancestor.setPotentialProjectReference(project.canonicalConfigFilePath);
                    }
                    project = ancestor;
                }
            };
            /*@internal*/
            ProjectService.prototype.loadAncestorProjectTree = function (forProjects) {
                forProjects = forProjects || ts.mapDefinedEntries(this.configuredProjects, function (key, project) { return !project.isInitialLoadPending() ? [key, true] : undefined; });
                var seenProjects = new ts.Set();
                // Work on array copy as we could add more projects as part of callback
                for (var _i = 0, _a = ts.arrayFrom(this.configuredProjects.values()); _i < _a.length; _i++) {
                    var project = _a[_i];
                    // If this project has potential project reference for any of the project we are loading ancestor tree for
                    // load this project first
                    if (forEachPotentialProjectReference(project, function (potentialRefPath) { return forProjects.has(potentialRefPath); })) {
                        updateProjectIfDirty(project);
                    }
                    this.ensureProjectChildren(project, forProjects, seenProjects);
                }
            };
            ProjectService.prototype.ensureProjectChildren = function (project, forProjects, seenProjects) {
                var _a;
                if (!ts.tryAddToSet(seenProjects, project.canonicalConfigFilePath))
                    return;
                // If this project disables child load ignore it
                if (project.getCompilerOptions().disableReferencedProjectLoad)
                    return;
                var children = (_a = project.getCurrentProgram()) === null || _a === void 0 ? void 0 : _a.getResolvedProjectReferences();
                if (!children)
                    return;
                for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
                    var child = children_1[_i];
                    if (!child)
                        continue;
                    var referencedProject = ts.forEachResolvedProjectReference(child.references, function (ref) { return forProjects.has(ref.sourceFile.path) ? ref : undefined; });
                    if (!referencedProject)
                        continue;
                    // Load this project,
                    var configFileName = server.toNormalizedPath(child.sourceFile.fileName);
                    var childProject = project.projectService.findConfiguredProjectByProjectName(configFileName) ||
                        project.projectService.createAndLoadConfiguredProject(configFileName, "Creating project referenced by : ".concat(project.projectName, " as it references project ").concat(referencedProject.sourceFile.fileName));
                    updateProjectIfDirty(childProject);
                    // Ensure children for this project
                    this.ensureProjectChildren(childProject, forProjects, seenProjects);
                }
            };
            ProjectService.prototype.cleanupAfterOpeningFile = function (toRetainConfigProjects) {
                // This was postponed from closeOpenFile to after opening next file,
                // so that we can reuse the project if we need to right away
                this.removeOrphanConfiguredProjects(toRetainConfigProjects);
                // Remove orphan inferred projects now that we have reused projects
                // We need to create a duplicate because we cant guarantee order after removal
                for (var _i = 0, _a = this.inferredProjects.slice(); _i < _a.length; _i++) {
                    var inferredProject = _a[_i];
                    if (inferredProject.isOrphan()) {
                        this.removeProject(inferredProject);
                    }
                }
                // Delete the orphan files here because there might be orphan script infos (which are not part of project)
                // when some file/s were closed which resulted in project removal.
                // It was then postponed to cleanup these script infos so that they can be reused if
                // the file from that old project is reopened because of opening file from here.
                this.removeOrphanScriptInfos();
            };
            ProjectService.prototype.openClientFileWithNormalizedPath = function (fileName, fileContent, scriptKind, hasMixedContent, projectRootPath) {
                var info = this.getOrCreateOpenScriptInfo(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath);
                var _a = this.assignProjectToOpenedScriptInfo(info), retainProjects = _a.retainProjects, result = __rest(_a, ["retainProjects"]);
                this.cleanupAfterOpeningFile(retainProjects);
                this.telemetryOnOpenFile(info);
                this.printProjects();
                return result;
            };
            ProjectService.prototype.removeOrphanConfiguredProjects = function (toRetainConfiguredProjects) {
                var _this = this;
                var toRemoveConfiguredProjects = new ts.Map(this.configuredProjects);
                var markOriginalProjectsAsUsed = function (project) {
                    if (!project.isOrphan() && project.originalConfiguredProjects) {
                        project.originalConfiguredProjects.forEach(function (_value, configuredProjectPath) {
                            var project = _this.getConfiguredProjectByCanonicalConfigFilePath(configuredProjectPath);
                            return project && retainConfiguredProject(project);
                        });
                    }
                };
                if (toRetainConfiguredProjects) {
                    if (ts.isArray(toRetainConfiguredProjects)) {
                        toRetainConfiguredProjects.forEach(retainConfiguredProject);
                    }
                    else {
                        retainConfiguredProject(toRetainConfiguredProjects);
                    }
                }
                // Do not remove configured projects that are used as original projects of other
                this.inferredProjects.forEach(markOriginalProjectsAsUsed);
                this.externalProjects.forEach(markOriginalProjectsAsUsed);
                this.configuredProjects.forEach(function (project) {
                    // If project has open ref (there are more than zero references from external project/open file), keep it alive as well as any project it references
                    if (project.hasOpenRef()) {
                        retainConfiguredProject(project);
                    }
                    else if (toRemoveConfiguredProjects.has(project.canonicalConfigFilePath)) {
                        // If the configured project for project reference has more than zero references, keep it alive
                        forEachReferencedProject(project, function (ref) { return isRetained(ref) && retainConfiguredProject(project); });
                    }
                });
                // Remove all the non marked projects
                toRemoveConfiguredProjects.forEach(function (project) { return _this.removeProject(project); });
                function isRetained(project) {
                    return project.hasOpenRef() || !toRemoveConfiguredProjects.has(project.canonicalConfigFilePath);
                }
                function retainConfiguredProject(project) {
                    if (toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath)) {
                        // Keep original projects used
                        markOriginalProjectsAsUsed(project);
                        // Keep all the references alive
                        forEachReferencedProject(project, retainConfiguredProject);
                    }
                }
            };
            ProjectService.prototype.removeOrphanScriptInfos = function () {
                var _this = this;
                var toRemoveScriptInfos = new ts.Map(this.filenameToScriptInfo);
                this.filenameToScriptInfo.forEach(function (info) {
                    // If script info is open or orphan, retain it and its dependencies
                    if (!info.isScriptOpen() && info.isOrphan() && !info.isContainedByBackgroundProject()) {
                        // Otherwise if there is any source info that is alive, this alive too
                        if (!info.sourceMapFilePath)
                            return;
                        var sourceInfos = void 0;
                        if (ts.isString(info.sourceMapFilePath)) {
                            var sourceMapInfo = _this.getScriptInfoForPath(info.sourceMapFilePath);
                            sourceInfos = sourceMapInfo && sourceMapInfo.sourceInfos;
                        }
                        else {
                            sourceInfos = info.sourceMapFilePath.sourceInfos;
                        }
                        if (!sourceInfos)
                            return;
                        if (!ts.forEachKey(sourceInfos, function (path) {
                            var info = _this.getScriptInfoForPath(path);
                            return !!info && (info.isScriptOpen() || !info.isOrphan());
                        })) {
                            return;
                        }
                    }
                    // Retain this script info
                    toRemoveScriptInfos.delete(info.path);
                    if (info.sourceMapFilePath) {
                        var sourceInfos = void 0;
                        if (ts.isString(info.sourceMapFilePath)) {
                            // And map file info and source infos
                            toRemoveScriptInfos.delete(info.sourceMapFilePath);
                            var sourceMapInfo = _this.getScriptInfoForPath(info.sourceMapFilePath);
                            sourceInfos = sourceMapInfo && sourceMapInfo.sourceInfos;
                        }
                        else {
                            sourceInfos = info.sourceMapFilePath.sourceInfos;
                        }
                        if (sourceInfos) {
                            sourceInfos.forEach(function (_value, path) { return toRemoveScriptInfos.delete(path); });
                        }
                    }
                });
                toRemoveScriptInfos.forEach(function (info) {
                    // if there are not projects that include this script info - delete it
                    _this.stopWatchingScriptInfo(info);
                    _this.deleteScriptInfo(info);
                    info.closeSourceMapFileWatcher();
                });
            };
            ProjectService.prototype.telemetryOnOpenFile = function (scriptInfo) {
                if (this.serverMode !== ts.LanguageServiceMode.Semantic || !this.eventHandler || !scriptInfo.isJavaScript() || !ts.addToSeen(this.allJsFilesForOpenFileTelemetry, scriptInfo.path)) {
                    return;
                }
                var project = scriptInfo.getDefaultProject();
                if (!project.languageServiceEnabled) {
                    return;
                }
                var sourceFile = project.getSourceFile(scriptInfo.path);
                var checkJs = !!sourceFile && !!sourceFile.checkJsDirective;
                this.eventHandler({ eventName: server.OpenFileInfoTelemetryEvent, data: { info: { checkJs: checkJs } } });
            };
            ProjectService.prototype.closeClientFile = function (uncheckedFileName, skipAssignOrphanScriptInfosToInferredProject) {
                var info = this.getScriptInfoForNormalizedPath(server.toNormalizedPath(uncheckedFileName));
                var result = info ? this.closeOpenFile(info, skipAssignOrphanScriptInfosToInferredProject) : false;
                if (!skipAssignOrphanScriptInfosToInferredProject) {
                    this.printProjects();
                }
                return result;
            };
            ProjectService.prototype.collectChanges = function (lastKnownProjectVersions, currentProjects, includeProjectReferenceRedirectInfo, result) {
                var _loop_5 = function (proj) {
                    var knownProject = ts.find(lastKnownProjectVersions, function (p) { return p.projectName === proj.getProjectName(); });
                    result.push(proj.getChangesSinceVersion(knownProject && knownProject.version, includeProjectReferenceRedirectInfo));
                };
                for (var _i = 0, currentProjects_1 = currentProjects; _i < currentProjects_1.length; _i++) {
                    var proj = currentProjects_1[_i];
                    _loop_5(proj);
                }
            };
            /* @internal */
            ProjectService.prototype.synchronizeProjectList = function (knownProjects, includeProjectReferenceRedirectInfo) {
                var files = [];
                this.collectChanges(knownProjects, this.externalProjects, includeProjectReferenceRedirectInfo, files);
                this.collectChanges(knownProjects, ts.arrayFrom(this.configuredProjects.values()), includeProjectReferenceRedirectInfo, files);
                this.collectChanges(knownProjects, this.inferredProjects, includeProjectReferenceRedirectInfo, files);
                return files;
            };
            /* @internal */
            ProjectService.prototype.applyChangesInOpenFiles = function (openFiles, changedFiles, closedFiles) {
                var _this = this;
                var openScriptInfos;
                var assignOrphanScriptInfosToInferredProject = false;
                if (openFiles) {
                    while (true) {
                        var iterResult = openFiles.next();
                        if (iterResult.done)
                            break;
                        var file = iterResult.value;
                        // Create script infos so we have the new content for all the open files before we do any updates to projects
                        var info = this.getOrCreateOpenScriptInfo(server.toNormalizedPath(file.fileName), file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent, file.projectRootPath ? server.toNormalizedPath(file.projectRootPath) : undefined);
                        (openScriptInfos || (openScriptInfos = [])).push(info);
                    }
                }
                if (changedFiles) {
                    while (true) {
                        var iterResult = changedFiles.next();
                        if (iterResult.done)
                            break;
                        var file = iterResult.value;
                        var scriptInfo = this.getScriptInfo(file.fileName);
                        ts.Debug.assert(!!scriptInfo);
                        // Make edits to script infos and marks containing project as dirty
                        this.applyChangesToFile(scriptInfo, file.changes);
                    }
                }
                if (closedFiles) {
                    for (var _i = 0, closedFiles_1 = closedFiles; _i < closedFiles_1.length; _i++) {
                        var file = closedFiles_1[_i];
                        // Close files, but dont assign projects to orphan open script infos, that part comes later
                        assignOrphanScriptInfosToInferredProject = this.closeClientFile(file, /*skipAssignOrphanScriptInfosToInferredProject*/ true) || assignOrphanScriptInfosToInferredProject;
                    }
                }
                // All the script infos now exist, so ok to go update projects for open files
                var retainProjects;
                if (openScriptInfos) {
                    retainProjects = ts.flatMap(openScriptInfos, function (info) { return _this.assignProjectToOpenedScriptInfo(info).retainProjects; });
                }
                // While closing files there could be open files that needed assigning new inferred projects, do it now
                if (assignOrphanScriptInfosToInferredProject) {
                    this.assignOrphanScriptInfosToInferredProject();
                }
                if (openScriptInfos) {
                    // Cleanup projects
                    this.cleanupAfterOpeningFile(retainProjects);
                    // Telemetry
                    openScriptInfos.forEach(function (info) { return _this.telemetryOnOpenFile(info); });
                    this.printProjects();
                }
                else if (ts.length(closedFiles)) {
                    this.printProjects();
                }
            };
            /* @internal */
            ProjectService.prototype.applyChangesToFile = function (scriptInfo, changes) {
                while (true) {
                    var iterResult = changes.next();
                    if (iterResult.done)
                        break;
                    var change = iterResult.value;
                    scriptInfo.editContent(change.span.start, change.span.start + change.span.length, change.newText);
                }
            };
            ProjectService.prototype.closeConfiguredProjectReferencedFromExternalProject = function (configFile) {
                var configuredProject = this.findConfiguredProjectByProjectName(configFile);
                if (configuredProject) {
                    configuredProject.deleteExternalProjectReference();
                    if (!configuredProject.hasOpenRef()) {
                        this.removeProject(configuredProject);
                        return;
                    }
                }
            };
            ProjectService.prototype.closeExternalProject = function (uncheckedFileName) {
                var fileName = server.toNormalizedPath(uncheckedFileName);
                var configFiles = this.externalProjectToConfiguredProjectMap.get(fileName);
                if (configFiles) {
                    for (var _i = 0, configFiles_1 = configFiles; _i < configFiles_1.length; _i++) {
                        var configFile = configFiles_1[_i];
                        this.closeConfiguredProjectReferencedFromExternalProject(configFile);
                    }
                    this.externalProjectToConfiguredProjectMap.delete(fileName);
                }
                else {
                    // close external project
                    var externalProject = this.findExternalProjectByProjectName(uncheckedFileName);
                    if (externalProject) {
                        this.removeProject(externalProject);
                    }
                }
            };
            ProjectService.prototype.openExternalProjects = function (projects) {
                var _this = this;
                // record project list before the update
                var projectsToClose = ts.arrayToMap(this.externalProjects, function (p) { return p.getProjectName(); }, function (_) { return true; });
                ts.forEachKey(this.externalProjectToConfiguredProjectMap, function (externalProjectName) {
                    projectsToClose.set(externalProjectName, true);
                });
                for (var _i = 0, projects_3 = projects; _i < projects_3.length; _i++) {
                    var externalProject = projects_3[_i];
                    this.openExternalProject(externalProject);
                    // delete project that is present in input list
                    projectsToClose.delete(externalProject.projectFileName);
                }
                // close projects that were missing in the input list
                ts.forEachKey(projectsToClose, function (externalProjectName) {
                    _this.closeExternalProject(externalProjectName);
                });
            };
            ProjectService.escapeFilenameForRegex = function (filename) {
                return filename.replace(this.filenameEscapeRegexp, "\\$&");
            };
            ProjectService.prototype.resetSafeList = function () {
                this.safelist = defaultTypeSafeList;
            };
            ProjectService.prototype.applySafeList = function (proj) {
                var _this = this;
                var rootFiles = proj.rootFiles;
                var typeAcquisition = proj.typeAcquisition;
                ts.Debug.assert(!!typeAcquisition, "proj.typeAcquisition should be set by now");
                if (typeAcquisition.enable === false || typeAcquisition.disableFilenameBasedTypeAcquisition) {
                    return [];
                }
                var typeAcqInclude = typeAcquisition.include || (typeAcquisition.include = []);
                var excludeRules = [];
                var normalizedNames = rootFiles.map(function (f) { return ts.normalizeSlashes(f.fileName); });
                var excludedFiles = [];
                var _loop_6 = function (name) {
                    var rule = this_3.safelist[name];
                    for (var _b = 0, normalizedNames_1 = normalizedNames; _b < normalizedNames_1.length; _b++) {
                        var root = normalizedNames_1[_b];
                        if (rule.match.test(root)) {
                            this_3.logger.info("Excluding files based on rule ".concat(name, " matching file '").concat(root, "'"));
                            // If the file matches, collect its types packages and exclude rules
                            if (rule.types) {
                                for (var _c = 0, _d = rule.types; _c < _d.length; _c++) {
                                    var type = _d[_c];
                                    // Best-effort de-duping here - doesn't need to be unduplicated but
                                    // we don't want the list to become a 400-element array of just 'kendo'
                                    if (typeAcqInclude.indexOf(type) < 0) {
                                        typeAcqInclude.push(type);
                                    }
                                }
                            }
                            if (rule.exclude) {
                                var _loop_8 = function (exclude) {
                                    var processedRule = root.replace(rule.match, function () {
                                        var groups = [];
                                        for (var _i = 0; _i < arguments.length; _i++) {
                                            groups[_i] = arguments[_i];
                                        }
                                        return exclude.map(function (groupNumberOrString) {
                                            // RegExp group numbers are 1-based, but the first element in groups
                                            // is actually the original string, so it all works out in the end.
                                            if (typeof groupNumberOrString === "number") {
                                                if (!ts.isString(groups[groupNumberOrString])) {
                                                    // Specification was wrong - exclude nothing!
                                                    _this.logger.info("Incorrect RegExp specification in safelist rule ".concat(name, " - not enough groups"));
                                                    // * can't appear in a filename; escape it because it's feeding into a RegExp
                                                    return "\\*";
                                                }
                                                return ProjectService.escapeFilenameForRegex(groups[groupNumberOrString]);
                                            }
                                            return groupNumberOrString;
                                        }).join("");
                                    });
                                    if (excludeRules.indexOf(processedRule) === -1) {
                                        excludeRules.push(processedRule);
                                    }
                                };
                                for (var _e = 0, _f = rule.exclude; _e < _f.length; _e++) {
                                    var exclude = _f[_e];
                                    _loop_8(exclude);
                                }
                            }
                            else {
                                // If not rules listed, add the default rule to exclude the matched file
                                var escaped = ProjectService.escapeFilenameForRegex(root);
                                if (excludeRules.indexOf(escaped) < 0) {
                                    excludeRules.push(escaped);
                                }
                            }
                        }
                    }
                };
                var this_3 = this;
                for (var _i = 0, _a = Object.keys(this.safelist); _i < _a.length; _i++) {
                    var name = _a[_i];
                    _loop_6(name);
                }
                var excludeRegexes = excludeRules.map(function (e) { return new RegExp(e, "i"); });
                var filesToKeep = [];
                var _loop_7 = function (i) {
                    if (excludeRegexes.some(function (re) { return re.test(normalizedNames[i]); })) {
                        excludedFiles.push(normalizedNames[i]);
                    }
                    else {
                        var exclude = false;
                        if (typeAcquisition.enable || typeAcquisition.enableAutoDiscovery) {
                            var baseName = ts.getBaseFileName(ts.toFileNameLowerCase(normalizedNames[i]));
                            if (ts.fileExtensionIs(baseName, "js")) {
                                var inferredTypingName = ts.removeFileExtension(baseName);
                                var cleanedTypingName = ts.removeMinAndVersionNumbers(inferredTypingName);
                                var typeName = this_4.legacySafelist.get(cleanedTypingName);
                                if (typeName !== undefined) {
                                    this_4.logger.info("Excluded '".concat(normalizedNames[i], "' because it matched ").concat(cleanedTypingName, " from the legacy safelist"));
                                    excludedFiles.push(normalizedNames[i]);
                                    // *exclude* it from the project...
                                    exclude = true;
                                    // ... but *include* it in the list of types to acquire
                                    // Same best-effort dedupe as above
                                    if (typeAcqInclude.indexOf(typeName) < 0) {
                                        typeAcqInclude.push(typeName);
                                    }
                                }
                            }
                        }
                        if (!exclude) {
                            // Exclude any minified files that get this far
                            if (/^.+[\.-]min\.js$/.test(normalizedNames[i])) {
                                excludedFiles.push(normalizedNames[i]);
                            }
                            else {
                                filesToKeep.push(proj.rootFiles[i]);
                            }
                        }
                    }
                };
                var this_4 = this;
                for (var i = 0; i < proj.rootFiles.length; i++) {
                    _loop_7(i);
                }
                proj.rootFiles = filesToKeep;
                return excludedFiles;
            };
            ProjectService.prototype.openExternalProject = function (proj) {
                // typingOptions has been deprecated and is only supported for backward compatibility
                // purposes. It should be removed in future releases - use typeAcquisition instead.
                if (proj.typingOptions && !proj.typeAcquisition) {
                    var typeAcquisition = ts.convertEnableAutoDiscoveryToEnable(proj.typingOptions);
                    proj.typeAcquisition = typeAcquisition;
                }
                proj.typeAcquisition = proj.typeAcquisition || {};
                proj.typeAcquisition.include = proj.typeAcquisition.include || [];
                proj.typeAcquisition.exclude = proj.typeAcquisition.exclude || [];
                if (proj.typeAcquisition.enable === undefined) {
                    proj.typeAcquisition.enable = server.hasNoTypeScriptSource(proj.rootFiles.map(function (f) { return f.fileName; }));
                }
                var excludedFiles = this.applySafeList(proj);
                var tsConfigFiles;
                var rootFiles = [];
                for (var _i = 0, _a = proj.rootFiles; _i < _a.length; _i++) {
                    var file = _a[_i];
                    var normalized = server.toNormalizedPath(file.fileName);
                    if (server.getBaseConfigFileName(normalized)) {
                        if (this.serverMode === ts.LanguageServiceMode.Semantic && this.host.fileExists(normalized)) {
                            (tsConfigFiles || (tsConfigFiles = [])).push(normalized);
                        }
                    }
                    else {
                        rootFiles.push(file);
                    }
                }
                // sort config files to simplify comparison later
                if (tsConfigFiles) {
                    tsConfigFiles.sort();
                }
                var externalProject = this.findExternalProjectByProjectName(proj.projectFileName);
                var exisingConfigFiles;
                if (externalProject) {
                    externalProject.excludedFiles = excludedFiles;
                    if (!tsConfigFiles) {
                        var compilerOptions = convertCompilerOptions(proj.options);
                        var watchOptionsAndErrors = convertWatchOptions(proj.options, externalProject.getCurrentDirectory());
                        var lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(proj.projectFileName, compilerOptions, proj.rootFiles, externalFilePropertyReader);
                        if (lastFileExceededProgramSize) {
                            externalProject.disableLanguageService(lastFileExceededProgramSize);
                        }
                        else {
                            externalProject.enableLanguageService();
                        }
                        externalProject.setProjectErrors(watchOptionsAndErrors === null || watchOptionsAndErrors === void 0 ? void 0 : watchOptionsAndErrors.errors);
                        // external project already exists and not config files were added - update the project and return;
                        // The graph update here isnt postponed since any file open operation needs all updated external projects
                        this.updateRootAndOptionsOfNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, compilerOptions, proj.typeAcquisition, proj.options.compileOnSave, watchOptionsAndErrors === null || watchOptionsAndErrors === void 0 ? void 0 : watchOptionsAndErrors.watchOptions);
                        externalProject.updateGraph();
                        return;
                    }
                    // some config files were added to external project (that previously were not there)
                    // close existing project and later we'll open a set of configured projects for these files
                    this.closeExternalProject(proj.projectFileName);
                }
                else if (this.externalProjectToConfiguredProjectMap.get(proj.projectFileName)) {
                    // this project used to include config files
                    if (!tsConfigFiles) {
                        // config files were removed from the project - close existing external project which in turn will close configured projects
                        this.closeExternalProject(proj.projectFileName);
                    }
                    else {
                        // project previously had some config files - compare them with new set of files and close all configured projects that correspond to unused files
                        var oldConfigFiles = this.externalProjectToConfiguredProjectMap.get(proj.projectFileName);
                        var iNew = 0;
                        var iOld = 0;
                        while (iNew < tsConfigFiles.length && iOld < oldConfigFiles.length) {
                            var newConfig = tsConfigFiles[iNew];
                            var oldConfig = oldConfigFiles[iOld];
                            if (oldConfig < newConfig) {
                                this.closeConfiguredProjectReferencedFromExternalProject(oldConfig);
                                iOld++;
                            }
                            else if (oldConfig > newConfig) {
                                iNew++;
                            }
                            else {
                                // record existing config files so avoid extra add-refs
                                (exisingConfigFiles || (exisingConfigFiles = [])).push(oldConfig);
                                iOld++;
                                iNew++;
                            }
                        }
                        for (var i = iOld; i < oldConfigFiles.length; i++) {
                            // projects for all remaining old config files should be closed
                            this.closeConfiguredProjectReferencedFromExternalProject(oldConfigFiles[i]);
                        }
                    }
                }
                if (tsConfigFiles) {
                    // store the list of tsconfig files that belong to the external project
                    this.externalProjectToConfiguredProjectMap.set(proj.projectFileName, tsConfigFiles);
                    for (var _b = 0, tsConfigFiles_1 = tsConfigFiles; _b < tsConfigFiles_1.length; _b++) {
                        var tsconfigFile = tsConfigFiles_1[_b];
                        var project = this.findConfiguredProjectByProjectName(tsconfigFile);
                        if (!project) {
                            // errors are stored in the project, do not need to update the graph
                            project = this.getHostPreferences().lazyConfiguredProjectsFromExternalProject ?
                                this.createConfiguredProjectWithDelayLoad(tsconfigFile, "Creating configured project in external project: ".concat(proj.projectFileName)) :
                                this.createLoadAndUpdateConfiguredProject(tsconfigFile, "Creating configured project in external project: ".concat(proj.projectFileName));
                        }
                        if (project && !ts.contains(exisingConfigFiles, tsconfigFile)) {
                            // keep project alive even if no documents are opened - its lifetime is bound to the lifetime of containing external project
                            project.addExternalProjectReference();
                        }
                    }
                }
                else {
                    // no config files - remove the item from the collection
                    // Create external project and update its graph, do not delay update since
                    // any file open operation needs all updated external projects
                    this.externalProjectToConfiguredProjectMap.delete(proj.projectFileName);
                    var project = this.createExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typeAcquisition, excludedFiles);
                    project.updateGraph();
                }
            };
            ProjectService.prototype.hasDeferredExtension = function () {
                for (var _i = 0, _a = this.hostConfiguration.extraFileExtensions; _i < _a.length; _i++) { // TODO: GH#18217
                    var extension = _a[_i];
                    if (extension.scriptKind === 7 /* ScriptKind.Deferred */) {
                        return true;
                    }
                }
                return false;
            };
            ProjectService.prototype.configurePlugin = function (args) {
                // For any projects that already have the plugin loaded, configure the plugin
                this.forEachEnabledProject(function (project) { return project.onPluginConfigurationChanged(args.pluginName, args.configuration); });
                // Also save the current configuration to pass on to any projects that are yet to be loaded.
                // If a plugin is configured twice, only the latest configuration will be remembered.
                this.currentPluginConfigOverrides = this.currentPluginConfigOverrides || new ts.Map();
                this.currentPluginConfigOverrides.set(args.pluginName, args.configuration);
            };
            /*@internal*/
            ProjectService.prototype.getPackageJsonsVisibleToFile = function (fileName, rootDir) {
                var _this = this;
                var packageJsonCache = this.packageJsonCache;
                var rootPath = rootDir && this.toPath(rootDir);
                var filePath = this.toPath(fileName);
                var result = [];
                var processDirectory = function (directory) {
                    switch (packageJsonCache.directoryHasPackageJson(directory)) {
                        // Sync and check same directory again
                        case 3 /* Ternary.Maybe */:
                            packageJsonCache.searchDirectoryAndAncestors(directory);
                            return processDirectory(directory);
                        // Check package.json
                        case -1 /* Ternary.True */:
                            var packageJsonFileName = ts.combinePaths(directory, "package.json");
                            _this.watchPackageJsonFile(packageJsonFileName);
                            var info = packageJsonCache.getInDirectory(directory);
                            if (info)
                                result.push(info);
                    }
                    if (rootPath && rootPath === directory) {
                        return true;
                    }
                };
                ts.forEachAncestorDirectory(ts.getDirectoryPath(filePath), processDirectory);
                return result;
            };
            /*@internal*/
            ProjectService.prototype.getNearestAncestorDirectoryWithPackageJson = function (fileName) {
                var _this = this;
                return ts.forEachAncestorDirectory(fileName, function (directory) {
                    switch (_this.packageJsonCache.directoryHasPackageJson(_this.toPath(directory))) {
                        case -1 /* Ternary.True */: return directory;
                        case 0 /* Ternary.False */: return undefined;
                        case 3 /* Ternary.Maybe */:
                            return _this.host.fileExists(ts.combinePaths(directory, "package.json"))
                                ? directory
                                : undefined;
                    }
                });
            };
            /*@internal*/
            ProjectService.prototype.watchPackageJsonFile = function (path) {
                var _this = this;
                var watchers = this.packageJsonFilesMap || (this.packageJsonFilesMap = new ts.Map());
                if (!watchers.has(path)) {
                    this.invalidateProjectPackageJson(path);
                    watchers.set(path, this.watchFactory.watchFile(path, function (fileName, eventKind) {
                        var path = _this.toPath(fileName);
                        switch (eventKind) {
                            case ts.FileWatcherEventKind.Created:
                                return ts.Debug.fail();
                            case ts.FileWatcherEventKind.Changed:
                                _this.packageJsonCache.addOrUpdate(path);
                                _this.invalidateProjectPackageJson(path);
                                break;
                            case ts.FileWatcherEventKind.Deleted:
                                _this.packageJsonCache.delete(path);
                                _this.invalidateProjectPackageJson(path);
                                watchers.get(path).close();
                                watchers.delete(path);
                        }
                    }, ts.PollingInterval.Low, this.hostConfiguration.watchOptions, ts.WatchType.PackageJson));
                }
            };
            /*@internal*/
            ProjectService.prototype.onAddPackageJson = function (path) {
                this.packageJsonCache.addOrUpdate(path);
                this.watchPackageJsonFile(path);
            };
            /*@internal*/
            ProjectService.prototype.includePackageJsonAutoImports = function () {
                switch (this.hostConfiguration.preferences.includePackageJsonAutoImports) {
                    case "on": return 1 /* PackageJsonAutoImportPreference.On */;
                    case "off": return 0 /* PackageJsonAutoImportPreference.Off */;
                    default: return 2 /* PackageJsonAutoImportPreference.Auto */;
                }
            };
            /*@internal*/
            ProjectService.prototype.invalidateProjectPackageJson = function (packageJsonPath) {
                this.configuredProjects.forEach(invalidate);
                this.inferredProjects.forEach(invalidate);
                this.externalProjects.forEach(invalidate);
                function invalidate(project) {
                    if (packageJsonPath) {
                        project.onPackageJsonChange(packageJsonPath);
                    }
                    else {
                        project.onAutoImportProviderSettingsChanged();
                    }
                }
            };
            /*@internal*/
            ProjectService.prototype.getIncompleteCompletionsCache = function () {
                return this.incompleteCompletionsCache || (this.incompleteCompletionsCache = createIncompleteCompletionsCache());
            };
            /** Makes a filename safe to insert in a RegExp */
            ProjectService.filenameEscapeRegexp = /[-\/\\^$*+?.()|[\]{}]/g;
            return ProjectService;
        }());
        server.ProjectService = ProjectService;
        function createIncompleteCompletionsCache() {
            var info;
            return {
                get: function () {
                    return info;
                },
                set: function (newInfo) {
                    info = newInfo;
                },
                clear: function () {
                    info = undefined;
                }
            };
        }
        /* @internal */
        function isConfigFile(config) {
            return config.kind !== undefined;
        }
        server.isConfigFile = isConfigFile;
        function printProjectWithoutFileNames(project) {
            project.print(/*writeProjectFileNames*/ false);
        }
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/*@internal*/
var ts;
(function (ts) {
    var server;
    (function (server) {
        function createModuleSpecifierCache(host) {
            var containedNodeModulesWatchers;
            var cache;
            var currentKey;
            var result = {
                get: function (fromFileName, toFileName, preferences, options) {
                    if (!cache || currentKey !== key(fromFileName, preferences, options))
                        return undefined;
                    return cache.get(toFileName);
                },
                set: function (fromFileName, toFileName, preferences, options, modulePaths, moduleSpecifiers) {
                    ensureCache(fromFileName, preferences, options).set(toFileName, createInfo(modulePaths, moduleSpecifiers, /*isBlockedByPackageJsonDependencies*/ false));
                    // If any module specifiers were generated based off paths in node_modules,
                    // a package.json file in that package was read and is an input to the cached.
                    // Instead of watching each individual package.json file, set up a wildcard
                    // directory watcher for any node_modules referenced and clear the cache when
                    // it sees any changes.
                    if (moduleSpecifiers) {
                        for (var _i = 0, modulePaths_1 = modulePaths; _i < modulePaths_1.length; _i++) {
                            var p = modulePaths_1[_i];
                            if (p.isInNodeModules) {
                                // No trailing slash
                                var nodeModulesPath = p.path.substring(0, p.path.indexOf(ts.nodeModulesPathPart) + ts.nodeModulesPathPart.length - 1);
                                if (!(containedNodeModulesWatchers === null || containedNodeModulesWatchers === void 0 ? void 0 : containedNodeModulesWatchers.has(nodeModulesPath))) {
                                    (containedNodeModulesWatchers || (containedNodeModulesWatchers = new ts.Map())).set(nodeModulesPath, host.watchNodeModulesForPackageJsonChanges(nodeModulesPath));
                                }
                            }
                        }
                    }
                },
                setModulePaths: function (fromFileName, toFileName, preferences, options, modulePaths) {
                    var cache = ensureCache(fromFileName, preferences, options);
                    var info = cache.get(toFileName);
                    if (info) {
                        info.modulePaths = modulePaths;
                    }
                    else {
                        cache.set(toFileName, createInfo(modulePaths, /*moduleSpecifiers*/ undefined, /*isBlockedByPackageJsonDependencies*/ undefined));
                    }
                },
                setBlockedByPackageJsonDependencies: function (fromFileName, toFileName, preferences, options, isBlockedByPackageJsonDependencies) {
                    var cache = ensureCache(fromFileName, preferences, options);
                    var info = cache.get(toFileName);
                    if (info) {
                        info.isBlockedByPackageJsonDependencies = isBlockedByPackageJsonDependencies;
                    }
                    else {
                        cache.set(toFileName, createInfo(/*modulePaths*/ undefined, /*moduleSpecifiers*/ undefined, isBlockedByPackageJsonDependencies));
                    }
                },
                clear: function () {
                    containedNodeModulesWatchers === null || containedNodeModulesWatchers === void 0 ? void 0 : containedNodeModulesWatchers.forEach(function (watcher) { return watcher.close(); });
                    cache === null || cache === void 0 ? void 0 : cache.clear();
                    containedNodeModulesWatchers === null || containedNodeModulesWatchers === void 0 ? void 0 : containedNodeModulesWatchers.clear();
                    currentKey = undefined;
                },
                count: function () {
                    return cache ? cache.size : 0;
                }
            };
            if (ts.Debug.isDebugging) {
                Object.defineProperty(result, "__cache", { get: function () { return cache; } });
            }
            return result;
            function ensureCache(fromFileName, preferences, options) {
                var newKey = key(fromFileName, preferences, options);
                if (cache && (currentKey !== newKey)) {
                    result.clear();
                }
                currentKey = newKey;
                return cache || (cache = new ts.Map());
            }
            function key(fromFileName, preferences, options) {
                return "".concat(fromFileName, ",").concat(preferences.importModuleSpecifierEnding, ",").concat(preferences.importModuleSpecifierPreference, ",").concat(options.overrideImportMode);
            }
            function createInfo(modulePaths, moduleSpecifiers, isBlockedByPackageJsonDependencies) {
                return { modulePaths: modulePaths, moduleSpecifiers: moduleSpecifiers, isBlockedByPackageJsonDependencies: isBlockedByPackageJsonDependencies };
            }
        }
        server.createModuleSpecifierCache = createModuleSpecifierCache;
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/*@internal*/
var ts;
(function (ts) {
    var server;
    (function (server) {
        function createPackageJsonCache(host) {
            var packageJsons = new ts.Map();
            var directoriesWithoutPackageJson = new ts.Map();
            return {
                addOrUpdate: addOrUpdate,
                forEach: packageJsons.forEach.bind(packageJsons),
                get: packageJsons.get.bind(packageJsons),
                delete: function (fileName) {
                    packageJsons.delete(fileName);
                    directoriesWithoutPackageJson.set(ts.getDirectoryPath(fileName), true);
                },
                getInDirectory: function (directory) {
                    return packageJsons.get(ts.combinePaths(directory, "package.json")) || undefined;
                },
                directoryHasPackageJson: directoryHasPackageJson,
                searchDirectoryAndAncestors: function (directory) {
                    ts.forEachAncestorDirectory(directory, function (ancestor) {
                        if (directoryHasPackageJson(ancestor) !== 3 /* Ternary.Maybe */) {
                            return true;
                        }
                        var packageJsonFileName = host.toPath(ts.combinePaths(ancestor, "package.json"));
                        if (ts.tryFileExists(host, packageJsonFileName)) {
                            addOrUpdate(packageJsonFileName);
                        }
                        else {
                            directoriesWithoutPackageJson.set(ancestor, true);
                        }
                    });
                },
            };
            function addOrUpdate(fileName) {
                var packageJsonInfo = ts.Debug.checkDefined(ts.createPackageJsonInfo(fileName, host.host));
                packageJsons.set(fileName, packageJsonInfo);
                directoriesWithoutPackageJson.delete(ts.getDirectoryPath(fileName));
            }
            function directoryHasPackageJson(directory) {
                return packageJsons.has(ts.combinePaths(directory, "package.json")) ? -1 /* Ternary.True */ :
                    directoriesWithoutPackageJson.has(directory) ? 0 /* Ternary.False */ :
                        3 /* Ternary.Maybe */;
            }
        }
        server.createPackageJsonCache = createPackageJsonCache;
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
var ts;
(function (ts) {
    var server;
    (function (server) {
        server.nullCancellationToken = {
            isCancellationRequested: function () { return false; },
            setRequest: function () { return void 0; },
            resetRequest: function () { return void 0; }
        };
        function hrTimeToMilliseconds(time) {
            var seconds = time[0];
            var nanoseconds = time[1];
            return ((1e9 * seconds) + nanoseconds) / 1000000.0;
        }
        function isDeclarationFileInJSOnlyNonConfiguredProject(project, file) {
            // Checking for semantic diagnostics is an expensive process. We want to avoid it if we
            // know for sure it is not needed.
            // For instance, .d.ts files injected by ATA automatically do not produce any relevant
            // errors to a JS- only project.
            //
            // Note that configured projects can set skipLibCheck (on by default in jsconfig.json) to
            // disable checking for declaration files. We only need to verify for inferred projects (e.g.
            // miscellaneous context in VS) and external projects(e.g.VS.csproj project) with only JS
            // files.
            //
            // We still want to check .js files in a JS-only inferred or external project (e.g. if the
            // file has '// @ts-check').
            if ((server.isInferredProject(project) || server.isExternalProject(project)) &&
                project.isJsOnlyProject()) {
                var scriptInfo = project.getScriptInfoForNormalizedPath(file);
                return scriptInfo && !scriptInfo.isJavaScript();
            }
            return false;
        }
        function dtsChangeCanAffectEmit(compilationSettings) {
            return ts.getEmitDeclarations(compilationSettings) || !!compilationSettings.emitDecoratorMetadata;
        }
        function formatDiag(fileName, project, diag) {
            var scriptInfo = project.getScriptInfoForNormalizedPath(fileName); // TODO: GH#18217
            return {
                start: scriptInfo.positionToLineOffset(diag.start),
                end: scriptInfo.positionToLineOffset(diag.start + diag.length),
                text: ts.flattenDiagnosticMessageText(diag.messageText, "\n"),
                code: diag.code,
                category: ts.diagnosticCategoryName(diag),
                reportsUnnecessary: diag.reportsUnnecessary,
                reportsDeprecated: diag.reportsDeprecated,
                source: diag.source,
                relatedInformation: ts.map(diag.relatedInformation, formatRelatedInformation),
            };
        }
        function formatRelatedInformation(info) {
            if (!info.file) {
                return {
                    message: ts.flattenDiagnosticMessageText(info.messageText, "\n"),
                    category: ts.diagnosticCategoryName(info),
                    code: info.code
                };
            }
            return {
                span: {
                    start: convertToLocation(ts.getLineAndCharacterOfPosition(info.file, info.start)),
                    end: convertToLocation(ts.getLineAndCharacterOfPosition(info.file, info.start + info.length)),
                    file: info.file.fileName
                },
                message: ts.flattenDiagnosticMessageText(info.messageText, "\n"),
                category: ts.diagnosticCategoryName(info),
                code: info.code
            };
        }
        function convertToLocation(lineAndCharacter) {
            return { line: lineAndCharacter.line + 1, offset: lineAndCharacter.character + 1 };
        }
        function formatDiagnosticToProtocol(diag, includeFileName) {
            var start = (diag.file && convertToLocation(ts.getLineAndCharacterOfPosition(diag.file, diag.start))); // TODO: GH#18217
            var end = (diag.file && convertToLocation(ts.getLineAndCharacterOfPosition(diag.file, diag.start + diag.length))); // TODO: GH#18217
            var text = ts.flattenDiagnosticMessageText(diag.messageText, "\n");
            var code = diag.code, source = diag.source;
            var category = ts.diagnosticCategoryName(diag);
            var common = {
                start: start,
                end: end,
                text: text,
                code: code,
                category: category,
                reportsUnnecessary: diag.reportsUnnecessary,
                reportsDeprecated: diag.reportsDeprecated,
                source: source,
                relatedInformation: ts.map(diag.relatedInformation, formatRelatedInformation),
            };
            return includeFileName
                ? __assign(__assign({}, common), { fileName: diag.file && diag.file.fileName }) : common;
        }
        function allEditsBeforePos(edits, pos) {
            return edits.every(function (edit) { return ts.textSpanEnd(edit.span) < pos; });
        }
        server.CommandNames = server.protocol.CommandTypes;
        function formatMessage(msg, logger, byteLength, newLine) {
            var verboseLogging = logger.hasLevel(server.LogLevel.verbose);
            var json = JSON.stringify(msg);
            if (verboseLogging) {
                logger.info("".concat(msg.type, ":").concat(server.indent(json)));
            }
            var len = byteLength(json, "utf8");
            return "Content-Length: ".concat(1 + len, "\r\n\r\n").concat(json).concat(newLine);
        }
        server.formatMessage = formatMessage;
        /**
         * Represents operation that can schedule its next step to be executed later.
         * Scheduling is done via instance of NextStep. If on current step subsequent step was not scheduled - operation is assumed to be completed.
         */
        var MultistepOperation = /** @class */ (function () {
            function MultistepOperation(operationHost) {
                this.operationHost = operationHost;
            }
            MultistepOperation.prototype.startNew = function (action) {
                this.complete();
                this.requestId = this.operationHost.getCurrentRequestId();
                this.executeAction(action);
            };
            MultistepOperation.prototype.complete = function () {
                if (this.requestId !== undefined) {
                    this.operationHost.sendRequestCompletedEvent(this.requestId);
                    this.requestId = undefined;
                }
                this.setTimerHandle(undefined);
                this.setImmediateId(undefined);
            };
            MultistepOperation.prototype.immediate = function (action) {
                var _this = this;
                var requestId = this.requestId;
                ts.Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "immediate: incorrect request id");
                this.setImmediateId(this.operationHost.getServerHost().setImmediate(function () {
                    _this.immediateId = undefined;
                    _this.operationHost.executeWithRequestId(requestId, function () { return _this.executeAction(action); });
                }));
            };
            MultistepOperation.prototype.delay = function (ms, action) {
                var _this = this;
                var requestId = this.requestId;
                ts.Debug.assert(requestId === this.operationHost.getCurrentRequestId(), "delay: incorrect request id");
                this.setTimerHandle(this.operationHost.getServerHost().setTimeout(function () {
                    _this.timerHandle = undefined;
                    _this.operationHost.executeWithRequestId(requestId, function () { return _this.executeAction(action); });
                }, ms));
            };
            MultistepOperation.prototype.executeAction = function (action) {
                var stop = false;
                try {
                    if (this.operationHost.isCancellationRequested()) {
                        stop = true;
                        ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "stepCanceled", { seq: this.requestId, early: true });
                    }
                    else {
                        ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "stepAction", { seq: this.requestId });
                        action(this);
                        ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
                    }
                }
                catch (e) {
                    // Cancellation or an error may have left incomplete events on the tracing stack.
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.popAll();
                    stop = true;
                    // ignore cancellation request
                    if (e instanceof ts.OperationCanceledException) {
                        ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "stepCanceled", { seq: this.requestId });
                    }
                    else {
                        ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "stepError", { seq: this.requestId, message: e.message });
                        this.operationHost.logError(e, "delayed processing of request ".concat(this.requestId));
                    }
                }
                if (stop || !this.hasPendingWork()) {
                    this.complete();
                }
            };
            MultistepOperation.prototype.setTimerHandle = function (timerHandle) {
                if (this.timerHandle !== undefined) {
                    this.operationHost.getServerHost().clearTimeout(this.timerHandle);
                }
                this.timerHandle = timerHandle;
            };
            MultistepOperation.prototype.setImmediateId = function (immediateId) {
                if (this.immediateId !== undefined) {
                    this.operationHost.getServerHost().clearImmediate(this.immediateId);
                }
                this.immediateId = immediateId;
            };
            MultistepOperation.prototype.hasPendingWork = function () {
                return !!this.timerHandle || !!this.immediateId;
            };
            return MultistepOperation;
        }());
        /** @internal */
        function toEvent(eventName, body) {
            return {
                seq: 0,
                type: "event",
                event: eventName,
                body: body
            };
        }
        server.toEvent = toEvent;
        /**
         * This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
         */
        function combineProjectOutput(defaultValue, getValue, projects, action) {
            var outputs = ts.flatMapToMutable(ts.isArray(projects) ? projects : projects.projects, function (project) { return action(project, defaultValue); });
            if (!ts.isArray(projects) && projects.symLinkedProjects) {
                projects.symLinkedProjects.forEach(function (projects, path) {
                    var value = getValue(path);
                    outputs.push.apply(outputs, ts.flatMap(projects, function (project) { return action(project, value); }));
                });
            }
            return ts.deduplicate(outputs, ts.equateValues);
        }
        ;
        function createDocumentSpanSet() {
            return ts.createSet(function (_a) {
                var textSpan = _a.textSpan;
                return textSpan.start + 100003 * textSpan.length;
            }, ts.documentSpansEqual);
        }
        function combineProjectOutputForRenameLocations(projects, defaultProject, initialLocation, findInStrings, findInComments, _a) {
            var providePrefixAndSuffixTextForRename = _a.providePrefixAndSuffixTextForRename;
            var outputs = [];
            var seen = createDocumentSpanSet();
            combineProjectOutputWorker(projects, defaultProject, initialLocation, 
            /*isForRename*/ true, function (project, location, tryAddToTodo) {
                var projectOutputs = project.getLanguageService().findRenameLocations(location.fileName, location.pos, findInStrings, findInComments, providePrefixAndSuffixTextForRename);
                if (projectOutputs) {
                    for (var _i = 0, projectOutputs_1 = projectOutputs; _i < projectOutputs_1.length; _i++) {
                        var output = projectOutputs_1[_i];
                        if (!seen.has(output) && !tryAddToTodo(project, documentSpanLocation(output))) {
                            seen.add(output);
                            outputs.push(output);
                        }
                    }
                }
            });
            return outputs;
        }
        function getDefinitionLocation(defaultProject, initialLocation, isForRename) {
            var infos = defaultProject.getLanguageService().getDefinitionAtPosition(initialLocation.fileName, initialLocation.pos, /*searchOtherFilesOnly*/ false, isForRename);
            var info = infos && ts.firstOrUndefined(infos);
            return info && !info.isLocal ? { fileName: info.fileName, pos: info.textSpan.start } : undefined;
        }
        function combineProjectOutputForReferences(projects, defaultProject, initialLocation, logger) {
            var outputs = [];
            combineProjectOutputWorker(projects, defaultProject, initialLocation, 
            /*isForRename*/ false, function (project, location, getMappedLocation) {
                var _a, _b;
                logger.info("Finding references to ".concat(location.fileName, " position ").concat(location.pos, " in project ").concat(project.getProjectName()));
                var projectOutputs = project.getLanguageService().findReferences(location.fileName, location.pos);
                if (projectOutputs) {
                    var clearIsDefinition = ((_b = (_a = projectOutputs[0]) === null || _a === void 0 ? void 0 : _a.references[0]) === null || _b === void 0 ? void 0 : _b.isDefinition) === undefined;
                    var _loop_9 = function (referencedSymbol) {
                        var mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(referencedSymbol.definition));
                        var definition = mappedDefinitionFile === undefined ?
                            referencedSymbol.definition : __assign(__assign({}, referencedSymbol.definition), { textSpan: ts.createTextSpan(mappedDefinitionFile.pos, referencedSymbol.definition.textSpan.length), fileName: mappedDefinitionFile.fileName, contextSpan: getMappedContextSpan(referencedSymbol.definition, project) });
                        var symbolToAddTo = ts.find(outputs, function (o) { return ts.documentSpansEqual(o.definition, definition); });
                        if (!symbolToAddTo) {
                            symbolToAddTo = { definition: definition, references: [] };
                            outputs.push(symbolToAddTo);
                        }
                        for (var _c = 0, _d = referencedSymbol.references; _c < _d.length; _c++) {
                            var ref = _d[_c];
                            // If it's in a mapped file, that is added to the todo list by `getMappedLocation`.
                            if (!ts.contains(symbolToAddTo.references, ref, ts.documentSpansEqual) && !getMappedLocation(project, documentSpanLocation(ref))) {
                                if (clearIsDefinition) {
                                    delete ref.isDefinition;
                                }
                                symbolToAddTo.references.push(ref);
                            }
                        }
                    };
                    for (var _i = 0, projectOutputs_2 = projectOutputs; _i < projectOutputs_2.length; _i++) {
                        var referencedSymbol = projectOutputs_2[_i];
                        _loop_9(referencedSymbol);
                    }
                }
            });
            return outputs.filter(function (o) { return o.references.length !== 0; });
        }
        function forEachProjectInProjects(projects, path, cb) {
            for (var _i = 0, _a = ts.isArray(projects) ? projects : projects.projects; _i < _a.length; _i++) {
                var project = _a[_i];
                cb(project, path);
            }
            if (!ts.isArray(projects) && projects.symLinkedProjects) {
                projects.symLinkedProjects.forEach(function (symlinkedProjects, symlinkedPath) {
                    for (var _i = 0, symlinkedProjects_1 = symlinkedProjects; _i < symlinkedProjects_1.length; _i++) {
                        var project = symlinkedProjects_1[_i];
                        cb(project, symlinkedPath);
                    }
                });
            }
        }
        function combineProjectOutputWorker(projects, defaultProject, initialLocation, isForRename, cb) {
            var projectService = defaultProject.projectService;
            var toDo;
            var seenProjects = new ts.Set();
            forEachProjectInProjects(projects, initialLocation && initialLocation.fileName, function (project, path) {
                // TLocation should be either `DocumentPosition` or `undefined`. Since `initialLocation` is `TLocation` this cast should be valid.
                var location = (initialLocation ? { fileName: path, pos: initialLocation.pos } : undefined);
                toDo = callbackProjectAndLocation(project, location, projectService, toDo, seenProjects, cb);
            });
            // After initial references are collected, go over every other project and see if it has a reference for the symbol definition.
            if (initialLocation) {
                var defaultDefinition_1 = getDefinitionLocation(defaultProject, initialLocation, isForRename);
                if (defaultDefinition_1) {
                    var getGeneratedDefinition_1 = ts.memoize(function () { return defaultProject.isSourceOfProjectReferenceRedirect(defaultDefinition_1.fileName) ?
                        defaultDefinition_1 :
                        defaultProject.getLanguageService().getSourceMapper().tryGetGeneratedPosition(defaultDefinition_1); });
                    var getSourceDefinition_1 = ts.memoize(function () { return defaultProject.isSourceOfProjectReferenceRedirect(defaultDefinition_1.fileName) ?
                        defaultDefinition_1 :
                        defaultProject.getLanguageService().getSourceMapper().tryGetSourcePosition(defaultDefinition_1); });
                    projectService.loadAncestorProjectTree(seenProjects);
                    projectService.forEachEnabledProject(function (project) {
                        if (!addToSeen(seenProjects, project))
                            return;
                        var definition = mapDefinitionInProject(defaultDefinition_1, project, getGeneratedDefinition_1, getSourceDefinition_1);
                        if (definition) {
                            toDo = callbackProjectAndLocation(project, definition, projectService, toDo, seenProjects, cb);
                        }
                    });
                }
            }
            while (toDo && toDo.length) {
                var next = toDo.pop();
                ts.Debug.assertIsDefined(next);
                toDo = callbackProjectAndLocation(next.project, next.location, projectService, toDo, seenProjects, cb);
            }
        }
        function mapDefinitionInProject(definition, project, getGeneratedDefinition, getSourceDefinition) {
            // If the definition is actually from the project, definition is correct as is
            if (project.containsFile(server.toNormalizedPath(definition.fileName)) &&
                !isLocationProjectReferenceRedirect(project, definition)) {
                return definition;
            }
            var generatedDefinition = getGeneratedDefinition();
            if (generatedDefinition && project.containsFile(server.toNormalizedPath(generatedDefinition.fileName)))
                return generatedDefinition;
            var sourceDefinition = getSourceDefinition();
            return sourceDefinition && project.containsFile(server.toNormalizedPath(sourceDefinition.fileName)) ? sourceDefinition : undefined;
        }
        function isLocationProjectReferenceRedirect(project, location) {
            if (!location)
                return false;
            var program = project.getLanguageService().getProgram();
            if (!program)
                return false;
            var sourceFile = program.getSourceFile(location.fileName);
            // It is possible that location is attached to project but
            // the program actually includes its redirect instead.
            // This happens when rootFile in project is one of the file from referenced project
            // Thus root is attached but program doesnt have the actual .ts file but .d.ts
            // If this is not the file we were actually looking, return rest of the toDo
            return !!sourceFile &&
                sourceFile.resolvedPath !== sourceFile.path &&
                sourceFile.resolvedPath !== project.toPath(location.fileName);
        }
        function callbackProjectAndLocation(project, location, projectService, toDo, seenProjects, cb) {
            if (project.getCancellationToken().isCancellationRequested())
                return undefined; // Skip rest of toDo if cancelled
            // If this is not the file we were actually looking, return rest of the toDo
            if (isLocationProjectReferenceRedirect(project, location))
                return toDo;
            cb(project, location, function (innerProject, location) {
                addToSeen(seenProjects, project);
                var originalLocation = projectService.getOriginalLocationEnsuringConfiguredProject(innerProject, location);
                if (!originalLocation)
                    return undefined;
                var originalScriptInfo = projectService.getScriptInfo(originalLocation.fileName);
                toDo = toDo || [];
                for (var _i = 0, _a = originalScriptInfo.containingProjects; _i < _a.length; _i++) {
                    var project_1 = _a[_i];
                    addToTodo(project_1, originalLocation, toDo, seenProjects);
                }
                var symlinkedProjectsMap = projectService.getSymlinkedProjects(originalScriptInfo);
                if (symlinkedProjectsMap) {
                    symlinkedProjectsMap.forEach(function (symlinkedProjects, symlinkedPath) {
                        for (var _i = 0, symlinkedProjects_2 = symlinkedProjects; _i < symlinkedProjects_2.length; _i++) {
                            var symlinkedProject = symlinkedProjects_2[_i];
                            addToTodo(symlinkedProject, { fileName: symlinkedPath, pos: originalLocation.pos }, toDo, seenProjects);
                        }
                    });
                }
                return originalLocation === location ? undefined : originalLocation;
            });
            return toDo;
        }
        function addToTodo(project, location, toDo, seenProjects) {
            if (!project.isOrphan() && addToSeen(seenProjects, project))
                toDo.push({ project: project, location: location });
        }
        function addToSeen(seenProjects, project) {
            return ts.tryAddToSet(seenProjects, getProjectKey(project));
        }
        function getProjectKey(project) {
            return server.isConfiguredProject(project) ? project.canonicalConfigFilePath : project.getProjectName();
        }
        function documentSpanLocation(_a) {
            var fileName = _a.fileName, textSpan = _a.textSpan;
            return { fileName: fileName, pos: textSpan.start };
        }
        function getMappedLocation(location, project) {
            var mapsTo = project.getSourceMapper().tryGetSourcePosition(location);
            return mapsTo && project.projectService.fileExists(server.toNormalizedPath(mapsTo.fileName)) ? mapsTo : undefined;
        }
        function getMappedDocumentSpan(documentSpan, project) {
            var newPosition = getMappedLocation(documentSpanLocation(documentSpan), project);
            if (!newPosition)
                return undefined;
            return {
                fileName: newPosition.fileName,
                textSpan: {
                    start: newPosition.pos,
                    length: documentSpan.textSpan.length
                },
                originalFileName: documentSpan.fileName,
                originalTextSpan: documentSpan.textSpan,
                contextSpan: getMappedContextSpan(documentSpan, project),
                originalContextSpan: documentSpan.contextSpan
            };
        }
        function getMappedContextSpan(documentSpan, project) {
            var contextSpanStart = documentSpan.contextSpan && getMappedLocation({ fileName: documentSpan.fileName, pos: documentSpan.contextSpan.start }, project);
            var contextSpanEnd = documentSpan.contextSpan && getMappedLocation({ fileName: documentSpan.fileName, pos: documentSpan.contextSpan.start + documentSpan.contextSpan.length }, project);
            return contextSpanStart && contextSpanEnd ?
                { start: contextSpanStart.pos, length: contextSpanEnd.pos - contextSpanStart.pos } :
                undefined;
        }
        var invalidPartialSemanticModeCommands = [
            server.CommandNames.OpenExternalProject,
            server.CommandNames.OpenExternalProjects,
            server.CommandNames.CloseExternalProject,
            server.CommandNames.SynchronizeProjectList,
            server.CommandNames.EmitOutput,
            server.CommandNames.CompileOnSaveAffectedFileList,
            server.CommandNames.CompileOnSaveEmitFile,
            server.CommandNames.CompilerOptionsDiagnosticsFull,
            server.CommandNames.EncodedSemanticClassificationsFull,
            server.CommandNames.SemanticDiagnosticsSync,
            server.CommandNames.SuggestionDiagnosticsSync,
            server.CommandNames.GeterrForProject,
            server.CommandNames.Reload,
            server.CommandNames.ReloadProjects,
            server.CommandNames.GetCodeFixes,
            server.CommandNames.GetCodeFixesFull,
            server.CommandNames.GetCombinedCodeFix,
            server.CommandNames.GetCombinedCodeFixFull,
            server.CommandNames.ApplyCodeActionCommand,
            server.CommandNames.GetSupportedCodeFixes,
            server.CommandNames.GetApplicableRefactors,
            server.CommandNames.GetEditsForRefactor,
            server.CommandNames.GetEditsForRefactorFull,
            server.CommandNames.OrganizeImports,
            server.CommandNames.OrganizeImportsFull,
            server.CommandNames.GetEditsForFileRename,
            server.CommandNames.GetEditsForFileRenameFull,
            server.CommandNames.ConfigurePlugin,
            server.CommandNames.PrepareCallHierarchy,
            server.CommandNames.ProvideCallHierarchyIncomingCalls,
            server.CommandNames.ProvideCallHierarchyOutgoingCalls,
        ];
        var invalidSyntacticModeCommands = __spreadArray(__spreadArray([], invalidPartialSemanticModeCommands, true), [
            server.CommandNames.Definition,
            server.CommandNames.DefinitionFull,
            server.CommandNames.DefinitionAndBoundSpan,
            server.CommandNames.DefinitionAndBoundSpanFull,
            server.CommandNames.TypeDefinition,
            server.CommandNames.Implementation,
            server.CommandNames.ImplementationFull,
            server.CommandNames.References,
            server.CommandNames.ReferencesFull,
            server.CommandNames.Rename,
            server.CommandNames.RenameLocationsFull,
            server.CommandNames.RenameInfoFull,
            server.CommandNames.Quickinfo,
            server.CommandNames.QuickinfoFull,
            server.CommandNames.CompletionInfo,
            server.CommandNames.Completions,
            server.CommandNames.CompletionsFull,
            server.CommandNames.CompletionDetails,
            server.CommandNames.CompletionDetailsFull,
            server.CommandNames.SignatureHelp,
            server.CommandNames.SignatureHelpFull,
            server.CommandNames.Navto,
            server.CommandNames.NavtoFull,
            server.CommandNames.Occurrences,
            server.CommandNames.DocumentHighlights,
            server.CommandNames.DocumentHighlightsFull,
        ], false);
        var Session = /** @class */ (function () {
            function Session(opts) {
                var _a;
                var _this = this;
                this.changeSeq = 0;
                this.handlers = new ts.Map(ts.getEntries((_a = {},
                    _a[server.CommandNames.Status] = function () {
                        var response = { version: ts.version }; // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier
                        return _this.requiredResponse(response);
                    },
                    _a[server.CommandNames.OpenExternalProject] = function (request) {
                        _this.projectService.openExternalProject(request.arguments);
                        // TODO: GH#20447 report errors
                        return _this.requiredResponse(/*response*/ true);
                    },
                    _a[server.CommandNames.OpenExternalProjects] = function (request) {
                        _this.projectService.openExternalProjects(request.arguments.projects);
                        // TODO: GH#20447 report errors
                        return _this.requiredResponse(/*response*/ true);
                    },
                    _a[server.CommandNames.CloseExternalProject] = function (request) {
                        _this.projectService.closeExternalProject(request.arguments.projectFileName);
                        // TODO: GH#20447 report errors
                        return _this.requiredResponse(/*response*/ true);
                    },
                    _a[server.CommandNames.SynchronizeProjectList] = function (request) {
                        var result = _this.projectService.synchronizeProjectList(request.arguments.knownProjects, request.arguments.includeProjectReferenceRedirectInfo);
                        if (!result.some(function (p) { return p.projectErrors && p.projectErrors.length !== 0; })) {
                            return _this.requiredResponse(result);
                        }
                        var converted = ts.map(result, function (p) {
                            if (!p.projectErrors || p.projectErrors.length === 0) {
                                return p;
                            }
                            return {
                                info: p.info,
                                changes: p.changes,
                                files: p.files,
                                projectErrors: _this.convertToDiagnosticsWithLinePosition(p.projectErrors, /*scriptInfo*/ undefined)
                            };
                        });
                        return _this.requiredResponse(converted);
                    },
                    _a[server.CommandNames.UpdateOpen] = function (request) {
                        _this.changeSeq++;
                        _this.projectService.applyChangesInOpenFiles(request.arguments.openFiles && ts.mapIterator(ts.arrayIterator(request.arguments.openFiles), function (file) { return ({
                            fileName: file.file,
                            content: file.fileContent,
                            scriptKind: file.scriptKindName,
                            projectRootPath: file.projectRootPath
                        }); }), request.arguments.changedFiles && ts.mapIterator(ts.arrayIterator(request.arguments.changedFiles), function (file) { return ({
                            fileName: file.fileName,
                            changes: ts.mapDefinedIterator(ts.arrayReverseIterator(file.textChanges), function (change) {
                                var scriptInfo = ts.Debug.checkDefined(_this.projectService.getScriptInfo(file.fileName));
                                var start = scriptInfo.lineOffsetToPosition(change.start.line, change.start.offset);
                                var end = scriptInfo.lineOffsetToPosition(change.end.line, change.end.offset);
                                return start >= 0 ? { span: { start: start, length: end - start }, newText: change.newText } : undefined;
                            })
                        }); }), request.arguments.closedFiles);
                        return _this.requiredResponse(/*response*/ true);
                    },
                    _a[server.CommandNames.ApplyChangedToOpenFiles] = function (request) {
                        _this.changeSeq++;
                        _this.projectService.applyChangesInOpenFiles(request.arguments.openFiles && ts.arrayIterator(request.arguments.openFiles), request.arguments.changedFiles && ts.mapIterator(ts.arrayIterator(request.arguments.changedFiles), function (file) { return ({
                            fileName: file.fileName,
                            // apply changes in reverse order
                            changes: ts.arrayReverseIterator(file.changes)
                        }); }), request.arguments.closedFiles);
                        // TODO: report errors
                        return _this.requiredResponse(/*response*/ true);
                    },
                    _a[server.CommandNames.Exit] = function () {
                        _this.exit();
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.Definition] = function (request) {
                        return _this.requiredResponse(_this.getDefinition(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.DefinitionFull] = function (request) {
                        return _this.requiredResponse(_this.getDefinition(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.DefinitionAndBoundSpan] = function (request) {
                        return _this.requiredResponse(_this.getDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.DefinitionAndBoundSpanFull] = function (request) {
                        return _this.requiredResponse(_this.getDefinitionAndBoundSpan(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.FindSourceDefinition] = function (request) {
                        return _this.requiredResponse(_this.findSourceDefinition(request.arguments));
                    },
                    _a[server.CommandNames.EmitOutput] = function (request) {
                        return _this.requiredResponse(_this.getEmitOutput(request.arguments));
                    },
                    _a[server.CommandNames.TypeDefinition] = function (request) {
                        return _this.requiredResponse(_this.getTypeDefinition(request.arguments));
                    },
                    _a[server.CommandNames.Implementation] = function (request) {
                        return _this.requiredResponse(_this.getImplementation(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.ImplementationFull] = function (request) {
                        return _this.requiredResponse(_this.getImplementation(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.References] = function (request) {
                        return _this.requiredResponse(_this.getReferences(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.ReferencesFull] = function (request) {
                        return _this.requiredResponse(_this.getReferences(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.Rename] = function (request) {
                        return _this.requiredResponse(_this.getRenameLocations(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.RenameLocationsFull] = function (request) {
                        return _this.requiredResponse(_this.getRenameLocations(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.RenameInfoFull] = function (request) {
                        return _this.requiredResponse(_this.getRenameInfo(request.arguments));
                    },
                    _a[server.CommandNames.Open] = function (request) {
                        _this.openClientFile(server.toNormalizedPath(request.arguments.file), request.arguments.fileContent, server.convertScriptKindName(request.arguments.scriptKindName), // TODO: GH#18217
                        request.arguments.projectRootPath ? server.toNormalizedPath(request.arguments.projectRootPath) : undefined);
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.Quickinfo] = function (request) {
                        return _this.requiredResponse(_this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.QuickinfoFull] = function (request) {
                        return _this.requiredResponse(_this.getQuickInfoWorker(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.GetOutliningSpans] = function (request) {
                        return _this.requiredResponse(_this.getOutliningSpans(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.GetOutliningSpansFull] = function (request) {
                        return _this.requiredResponse(_this.getOutliningSpans(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.TodoComments] = function (request) {
                        return _this.requiredResponse(_this.getTodoComments(request.arguments));
                    },
                    _a[server.CommandNames.Indentation] = function (request) {
                        return _this.requiredResponse(_this.getIndentation(request.arguments));
                    },
                    _a[server.CommandNames.NameOrDottedNameSpan] = function (request) {
                        return _this.requiredResponse(_this.getNameOrDottedNameSpan(request.arguments));
                    },
                    _a[server.CommandNames.BreakpointStatement] = function (request) {
                        return _this.requiredResponse(_this.getBreakpointStatement(request.arguments));
                    },
                    _a[server.CommandNames.BraceCompletion] = function (request) {
                        return _this.requiredResponse(_this.isValidBraceCompletion(request.arguments));
                    },
                    _a[server.CommandNames.DocCommentTemplate] = function (request) {
                        return _this.requiredResponse(_this.getDocCommentTemplate(request.arguments));
                    },
                    _a[server.CommandNames.GetSpanOfEnclosingComment] = function (request) {
                        return _this.requiredResponse(_this.getSpanOfEnclosingComment(request.arguments));
                    },
                    _a[server.CommandNames.FileReferences] = function (request) {
                        return _this.requiredResponse(_this.getFileReferences(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.FileReferencesFull] = function (request) {
                        return _this.requiredResponse(_this.getFileReferences(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.Format] = function (request) {
                        return _this.requiredResponse(_this.getFormattingEditsForRange(request.arguments));
                    },
                    _a[server.CommandNames.Formatonkey] = function (request) {
                        return _this.requiredResponse(_this.getFormattingEditsAfterKeystroke(request.arguments));
                    },
                    _a[server.CommandNames.FormatFull] = function (request) {
                        return _this.requiredResponse(_this.getFormattingEditsForDocumentFull(request.arguments));
                    },
                    _a[server.CommandNames.FormatonkeyFull] = function (request) {
                        return _this.requiredResponse(_this.getFormattingEditsAfterKeystrokeFull(request.arguments));
                    },
                    _a[server.CommandNames.FormatRangeFull] = function (request) {
                        return _this.requiredResponse(_this.getFormattingEditsForRangeFull(request.arguments));
                    },
                    _a[server.CommandNames.CompletionInfo] = function (request) {
                        return _this.requiredResponse(_this.getCompletions(request.arguments, server.CommandNames.CompletionInfo));
                    },
                    _a[server.CommandNames.Completions] = function (request) {
                        return _this.requiredResponse(_this.getCompletions(request.arguments, server.CommandNames.Completions));
                    },
                    _a[server.CommandNames.CompletionsFull] = function (request) {
                        return _this.requiredResponse(_this.getCompletions(request.arguments, server.CommandNames.CompletionsFull));
                    },
                    _a[server.CommandNames.CompletionDetails] = function (request) {
                        return _this.requiredResponse(_this.getCompletionEntryDetails(request.arguments, /*fullResult*/ false));
                    },
                    _a[server.CommandNames.CompletionDetailsFull] = function (request) {
                        return _this.requiredResponse(_this.getCompletionEntryDetails(request.arguments, /*fullResult*/ true));
                    },
                    _a[server.CommandNames.CompileOnSaveAffectedFileList] = function (request) {
                        return _this.requiredResponse(_this.getCompileOnSaveAffectedFileList(request.arguments));
                    },
                    _a[server.CommandNames.CompileOnSaveEmitFile] = function (request) {
                        return _this.requiredResponse(_this.emitFile(request.arguments));
                    },
                    _a[server.CommandNames.SignatureHelp] = function (request) {
                        return _this.requiredResponse(_this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.SignatureHelpFull] = function (request) {
                        return _this.requiredResponse(_this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.CompilerOptionsDiagnosticsFull] = function (request) {
                        return _this.requiredResponse(_this.getCompilerOptionsDiagnostics(request.arguments));
                    },
                    _a[server.CommandNames.EncodedSyntacticClassificationsFull] = function (request) {
                        return _this.requiredResponse(_this.getEncodedSyntacticClassifications(request.arguments));
                    },
                    _a[server.CommandNames.EncodedSemanticClassificationsFull] = function (request) {
                        return _this.requiredResponse(_this.getEncodedSemanticClassifications(request.arguments));
                    },
                    _a[server.CommandNames.Cleanup] = function () {
                        _this.cleanup();
                        return _this.requiredResponse(/*response*/ true);
                    },
                    _a[server.CommandNames.SemanticDiagnosticsSync] = function (request) {
                        return _this.requiredResponse(_this.getSemanticDiagnosticsSync(request.arguments));
                    },
                    _a[server.CommandNames.SyntacticDiagnosticsSync] = function (request) {
                        return _this.requiredResponse(_this.getSyntacticDiagnosticsSync(request.arguments));
                    },
                    _a[server.CommandNames.SuggestionDiagnosticsSync] = function (request) {
                        return _this.requiredResponse(_this.getSuggestionDiagnosticsSync(request.arguments));
                    },
                    _a[server.CommandNames.Geterr] = function (request) {
                        _this.errorCheck.startNew(function (next) { return _this.getDiagnostics(next, request.arguments.delay, request.arguments.files); });
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.GeterrForProject] = function (request) {
                        _this.errorCheck.startNew(function (next) { return _this.getDiagnosticsForProject(next, request.arguments.delay, request.arguments.file); });
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.Change] = function (request) {
                        _this.change(request.arguments);
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.Configure] = function (request) {
                        _this.projectService.setHostConfiguration(request.arguments);
                        _this.doOutput(/*info*/ undefined, server.CommandNames.Configure, request.seq, /*success*/ true);
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.Reload] = function (request) {
                        _this.reload(request.arguments, request.seq);
                        return _this.requiredResponse({ reloadFinished: true });
                    },
                    _a[server.CommandNames.Saveto] = function (request) {
                        var savetoArgs = request.arguments;
                        _this.saveToTmp(savetoArgs.file, savetoArgs.tmpfile);
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.Close] = function (request) {
                        var closeArgs = request.arguments;
                        _this.closeClientFile(closeArgs.file);
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.Navto] = function (request) {
                        return _this.requiredResponse(_this.getNavigateToItems(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.NavtoFull] = function (request) {
                        return _this.requiredResponse(_this.getNavigateToItems(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.Brace] = function (request) {
                        return _this.requiredResponse(_this.getBraceMatching(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.BraceFull] = function (request) {
                        return _this.requiredResponse(_this.getBraceMatching(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.NavBar] = function (request) {
                        return _this.requiredResponse(_this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.NavBarFull] = function (request) {
                        return _this.requiredResponse(_this.getNavigationBarItems(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.NavTree] = function (request) {
                        return _this.requiredResponse(_this.getNavigationTree(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.NavTreeFull] = function (request) {
                        return _this.requiredResponse(_this.getNavigationTree(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.Occurrences] = function (request) {
                        return _this.requiredResponse(_this.getOccurrences(request.arguments));
                    },
                    _a[server.CommandNames.DocumentHighlights] = function (request) {
                        return _this.requiredResponse(_this.getDocumentHighlights(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.DocumentHighlightsFull] = function (request) {
                        return _this.requiredResponse(_this.getDocumentHighlights(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.CompilerOptionsForInferredProjects] = function (request) {
                        _this.setCompilerOptionsForInferredProjects(request.arguments);
                        return _this.requiredResponse(/*response*/ true);
                    },
                    _a[server.CommandNames.ProjectInfo] = function (request) {
                        return _this.requiredResponse(_this.getProjectInfo(request.arguments));
                    },
                    _a[server.CommandNames.ReloadProjects] = function () {
                        _this.projectService.reloadProjects();
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.JsxClosingTag] = function (request) {
                        return _this.requiredResponse(_this.getJsxClosingTag(request.arguments));
                    },
                    _a[server.CommandNames.GetCodeFixes] = function (request) {
                        return _this.requiredResponse(_this.getCodeFixes(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.GetCodeFixesFull] = function (request) {
                        return _this.requiredResponse(_this.getCodeFixes(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.GetCombinedCodeFix] = function (request) {
                        return _this.requiredResponse(_this.getCombinedCodeFix(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.GetCombinedCodeFixFull] = function (request) {
                        return _this.requiredResponse(_this.getCombinedCodeFix(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.ApplyCodeActionCommand] = function (request) {
                        return _this.requiredResponse(_this.applyCodeActionCommand(request.arguments));
                    },
                    _a[server.CommandNames.GetSupportedCodeFixes] = function () {
                        return _this.requiredResponse(_this.getSupportedCodeFixes());
                    },
                    _a[server.CommandNames.GetApplicableRefactors] = function (request) {
                        return _this.requiredResponse(_this.getApplicableRefactors(request.arguments));
                    },
                    _a[server.CommandNames.GetEditsForRefactor] = function (request) {
                        return _this.requiredResponse(_this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.GetEditsForRefactorFull] = function (request) {
                        return _this.requiredResponse(_this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.OrganizeImports] = function (request) {
                        return _this.requiredResponse(_this.organizeImports(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.OrganizeImportsFull] = function (request) {
                        return _this.requiredResponse(_this.organizeImports(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.GetEditsForFileRename] = function (request) {
                        return _this.requiredResponse(_this.getEditsForFileRename(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.GetEditsForFileRenameFull] = function (request) {
                        return _this.requiredResponse(_this.getEditsForFileRename(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.ConfigurePlugin] = function (request) {
                        _this.configurePlugin(request.arguments);
                        _this.doOutput(/*info*/ undefined, server.CommandNames.ConfigurePlugin, request.seq, /*success*/ true);
                        return _this.notRequired();
                    },
                    _a[server.CommandNames.SelectionRange] = function (request) {
                        return _this.requiredResponse(_this.getSmartSelectionRange(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.SelectionRangeFull] = function (request) {
                        return _this.requiredResponse(_this.getSmartSelectionRange(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.PrepareCallHierarchy] = function (request) {
                        return _this.requiredResponse(_this.prepareCallHierarchy(request.arguments));
                    },
                    _a[server.CommandNames.ProvideCallHierarchyIncomingCalls] = function (request) {
                        return _this.requiredResponse(_this.provideCallHierarchyIncomingCalls(request.arguments));
                    },
                    _a[server.CommandNames.ProvideCallHierarchyOutgoingCalls] = function (request) {
                        return _this.requiredResponse(_this.provideCallHierarchyOutgoingCalls(request.arguments));
                    },
                    _a[server.CommandNames.ToggleLineComment] = function (request) {
                        return _this.requiredResponse(_this.toggleLineComment(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.ToggleLineCommentFull] = function (request) {
                        return _this.requiredResponse(_this.toggleLineComment(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.ToggleMultilineComment] = function (request) {
                        return _this.requiredResponse(_this.toggleMultilineComment(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.ToggleMultilineCommentFull] = function (request) {
                        return _this.requiredResponse(_this.toggleMultilineComment(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.CommentSelection] = function (request) {
                        return _this.requiredResponse(_this.commentSelection(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.CommentSelectionFull] = function (request) {
                        return _this.requiredResponse(_this.commentSelection(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.UncommentSelection] = function (request) {
                        return _this.requiredResponse(_this.uncommentSelection(request.arguments, /*simplifiedResult*/ true));
                    },
                    _a[server.CommandNames.UncommentSelectionFull] = function (request) {
                        return _this.requiredResponse(_this.uncommentSelection(request.arguments, /*simplifiedResult*/ false));
                    },
                    _a[server.CommandNames.ProvideInlayHints] = function (request) {
                        return _this.requiredResponse(_this.provideInlayHints(request.arguments));
                    },
                    _a)));
                this.host = opts.host;
                this.cancellationToken = opts.cancellationToken;
                this.typingsInstaller = opts.typingsInstaller;
                this.byteLength = opts.byteLength;
                this.hrtime = opts.hrtime;
                this.logger = opts.logger;
                this.canUseEvents = opts.canUseEvents;
                this.suppressDiagnosticEvents = opts.suppressDiagnosticEvents;
                this.noGetErrOnBackgroundUpdate = opts.noGetErrOnBackgroundUpdate;
                var throttleWaitMilliseconds = opts.throttleWaitMilliseconds;
                this.eventHandler = this.canUseEvents
                    ? opts.eventHandler || (function (event) { return _this.defaultEventHandler(event); })
                    : undefined;
                var multistepOperationHost = {
                    executeWithRequestId: function (requestId, action) { return _this.executeWithRequestId(requestId, action); },
                    getCurrentRequestId: function () { return _this.currentRequestId; },
                    getServerHost: function () { return _this.host; },
                    logError: function (err, cmd) { return _this.logError(err, cmd); },
                    sendRequestCompletedEvent: function (requestId) { return _this.sendRequestCompletedEvent(requestId); },
                    isCancellationRequested: function () { return _this.cancellationToken.isCancellationRequested(); }
                };
                this.errorCheck = new MultistepOperation(multistepOperationHost);
                var settings = {
                    host: this.host,
                    logger: this.logger,
                    cancellationToken: this.cancellationToken,
                    useSingleInferredProject: opts.useSingleInferredProject,
                    useInferredProjectPerProjectRoot: opts.useInferredProjectPerProjectRoot,
                    typingsInstaller: this.typingsInstaller,
                    throttleWaitMilliseconds: throttleWaitMilliseconds,
                    eventHandler: this.eventHandler,
                    suppressDiagnosticEvents: this.suppressDiagnosticEvents,
                    globalPlugins: opts.globalPlugins,
                    pluginProbeLocations: opts.pluginProbeLocations,
                    allowLocalPluginLoads: opts.allowLocalPluginLoads,
                    typesMapLocation: opts.typesMapLocation,
                    syntaxOnly: opts.syntaxOnly,
                    serverMode: opts.serverMode,
                    session: this
                };
                this.projectService = new server.ProjectService(settings);
                this.projectService.setPerformanceEventHandler(this.performanceEventHandler.bind(this));
                this.gcTimer = new server.GcTimer(this.host, /*delay*/ 7000, this.logger);
                // Make sure to setup handlers to throw error for not allowed commands on syntax server
                switch (this.projectService.serverMode) {
                    case ts.LanguageServiceMode.Semantic:
                        break;
                    case ts.LanguageServiceMode.PartialSemantic:
                        invalidPartialSemanticModeCommands.forEach(function (commandName) {
                            return _this.handlers.set(commandName, function (request) {
                                throw new Error("Request: ".concat(request.command, " not allowed in LanguageServiceMode.PartialSemantic"));
                            });
                        });
                        break;
                    case ts.LanguageServiceMode.Syntactic:
                        invalidSyntacticModeCommands.forEach(function (commandName) {
                            return _this.handlers.set(commandName, function (request) {
                                throw new Error("Request: ".concat(request.command, " not allowed in LanguageServiceMode.Syntactic"));
                            });
                        });
                        break;
                    default:
                        ts.Debug.assertNever(this.projectService.serverMode);
                }
            }
            Session.prototype.sendRequestCompletedEvent = function (requestId) {
                this.event({ request_seq: requestId }, "requestCompleted");
            };
            Session.prototype.addPerformanceData = function (key, value) {
                var _a;
                if (!this.performanceData) {
                    this.performanceData = {};
                }
                this.performanceData[key] = ((_a = this.performanceData[key]) !== null && _a !== void 0 ? _a : 0) + value;
            };
            Session.prototype.performanceEventHandler = function (event) {
                switch (event.kind) {
                    case "UpdateGraph":
                        this.addPerformanceData("updateGraphDurationMs", event.durationMs);
                        break;
                    case "CreatePackageJsonAutoImportProvider":
                        this.addPerformanceData("createAutoImportProviderProgramDurationMs", event.durationMs);
                        break;
                }
            };
            Session.prototype.defaultEventHandler = function (event) {
                switch (event.eventName) {
                    case server.ProjectsUpdatedInBackgroundEvent:
                        var openFiles = event.data.openFiles;
                        this.projectsUpdatedInBackgroundEvent(openFiles);
                        break;
                    case server.ProjectLoadingStartEvent:
                        var _a = event.data, project = _a.project, reason = _a.reason;
                        this.event({ projectName: project.getProjectName(), reason: reason }, server.ProjectLoadingStartEvent);
                        break;
                    case server.ProjectLoadingFinishEvent:
                        var finishProject = event.data.project;
                        this.event({ projectName: finishProject.getProjectName() }, server.ProjectLoadingFinishEvent);
                        break;
                    case server.LargeFileReferencedEvent:
                        var _b = event.data, file = _b.file, fileSize = _b.fileSize, maxFileSize_1 = _b.maxFileSize;
                        this.event({ file: file, fileSize: fileSize, maxFileSize: maxFileSize_1 }, server.LargeFileReferencedEvent);
                        break;
                    case server.ConfigFileDiagEvent:
                        var _c = event.data, triggerFile = _c.triggerFile, configFile = _c.configFileName, diagnostics = _c.diagnostics;
                        var bakedDiags = ts.map(diagnostics, function (diagnostic) { return formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ true); });
                        this.event({
                            triggerFile: triggerFile,
                            configFile: configFile,
                            diagnostics: bakedDiags
                        }, server.ConfigFileDiagEvent);
                        break;
                    case server.ProjectLanguageServiceStateEvent: {
                        var eventName = server.ProjectLanguageServiceStateEvent;
                        this.event({
                            projectName: event.data.project.getProjectName(),
                            languageServiceEnabled: event.data.languageServiceEnabled
                        }, eventName);
                        break;
                    }
                    case server.ProjectInfoTelemetryEvent: {
                        var eventName = "telemetry";
                        this.event({
                            telemetryEventName: event.eventName,
                            payload: event.data,
                        }, eventName);
                        break;
                    }
                }
            };
            Session.prototype.projectsUpdatedInBackgroundEvent = function (openFiles) {
                var _this = this;
                this.projectService.logger.info("got projects updated in background, updating diagnostics for ".concat(openFiles));
                if (openFiles.length) {
                    if (!this.suppressDiagnosticEvents && !this.noGetErrOnBackgroundUpdate) {
                        // For now only queue error checking for open files. We can change this to include non open files as well
                        this.errorCheck.startNew(function (next) { return _this.updateErrorCheck(next, openFiles, 100, /*requireOpen*/ true); });
                    }
                    // Send project changed event
                    this.event({
                        openFiles: openFiles
                    }, server.ProjectsUpdatedInBackgroundEvent);
                }
            };
            Session.prototype.logError = function (err, cmd) {
                this.logErrorWorker(err, cmd);
            };
            Session.prototype.logErrorWorker = function (err, cmd, fileRequest) {
                var msg = "Exception on executing command " + cmd;
                if (err.message) {
                    msg += ":\n" + server.indent(err.message);
                    if (err.stack) {
                        msg += "\n" + server.indent(err.stack);
                    }
                }
                if (this.logger.hasLevel(server.LogLevel.verbose)) {
                    if (fileRequest) {
                        try {
                            var _a = this.getFileAndProject(fileRequest), file = _a.file, project = _a.project;
                            var scriptInfo = project.getScriptInfoForNormalizedPath(file);
                            if (scriptInfo) {
                                var text = ts.getSnapshotText(scriptInfo.getSnapshot());
                                msg += "\n\nFile text of ".concat(fileRequest.file, ":").concat(server.indent(text), "\n");
                            }
                        }
                        catch (_b) { } // eslint-disable-line no-empty
                    }
                    if (err.ProgramFiles) {
                        msg += "\n\nProgram files: ".concat(JSON.stringify(err.ProgramFiles), "\n");
                        msg += "\n\nProjects::\n";
                        var counter_1 = 0;
                        var addProjectInfo = function (project) {
                            msg += "\nProject '".concat(project.projectName, "' (").concat(server.ProjectKind[project.projectKind], ") ").concat(counter_1, "\n");
                            msg += project.filesToString(/*writeProjectFileNames*/ true);
                            msg += "\n-----------------------------------------------\n";
                            counter_1++;
                        };
                        this.projectService.externalProjects.forEach(addProjectInfo);
                        this.projectService.configuredProjects.forEach(addProjectInfo);
                        this.projectService.inferredProjects.forEach(addProjectInfo);
                    }
                }
                this.logger.msg(msg, server.Msg.Err);
            };
            Session.prototype.send = function (msg) {
                if (msg.type === "event" && !this.canUseEvents) {
                    if (this.logger.hasLevel(server.LogLevel.verbose)) {
                        this.logger.info("Session does not support events: ignored event: ".concat(JSON.stringify(msg)));
                    }
                    return;
                }
                this.writeMessage(msg);
            };
            Session.prototype.writeMessage = function (msg) {
                var msgText = formatMessage(msg, this.logger, this.byteLength, this.host.newLine);
                ts.perfLogger.logEvent("Response message size: ".concat(msgText.length));
                this.host.write(msgText);
            };
            Session.prototype.event = function (body, eventName) {
                this.send(toEvent(eventName, body));
            };
            // For backwards-compatibility only.
            /** @deprecated */
            Session.prototype.output = function (info, cmdName, reqSeq, errorMsg) {
                this.doOutput(info, cmdName, reqSeq, /*success*/ !errorMsg, errorMsg); // TODO: GH#18217
            };
            Session.prototype.doOutput = function (info, cmdName, reqSeq, success, message) {
                var res = {
                    seq: 0,
                    type: "response",
                    command: cmdName,
                    request_seq: reqSeq,
                    success: success,
                    performanceData: this.performanceData
                };
                if (success) {
                    var metadata = void 0;
                    if (ts.isArray(info)) {
                        res.body = info;
                        metadata = info.metadata;
                        delete info.metadata;
                    }
                    else if (typeof info === "object") {
                        if (info.metadata) {
                            var _a = info, infoMetadata = _a.metadata, body = __rest(_a, ["metadata"]);
                            res.body = body;
                            metadata = infoMetadata;
                        }
                        else {
                            res.body = info;
                        }
                    }
                    else {
                        res.body = info;
                    }
                    if (metadata)
                        res.metadata = metadata;
                }
                else {
                    ts.Debug.assert(info === undefined);
                }
                if (message) {
                    res.message = message;
                }
                this.send(res);
            };
            Session.prototype.semanticCheck = function (file, project) {
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "semanticCheck", { file: file, configFilePath: project.canonicalConfigFilePath }); // undefined is fine if the cast fails
                var diags = isDeclarationFileInJSOnlyNonConfiguredProject(project, file)
                    ? server.emptyArray
                    : project.getLanguageService().getSemanticDiagnostics(file).filter(function (d) { return !!d.file; });
                this.sendDiagnosticsEvent(file, project, diags, "semanticDiag");
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
            };
            Session.prototype.syntacticCheck = function (file, project) {
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "syntacticCheck", { file: file, configFilePath: project.canonicalConfigFilePath }); // undefined is fine if the cast fails
                this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSyntacticDiagnostics(file), "syntaxDiag");
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
            };
            Session.prototype.suggestionCheck = function (file, project) {
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "suggestionCheck", { file: file, configFilePath: project.canonicalConfigFilePath }); // undefined is fine if the cast fails
                this.sendDiagnosticsEvent(file, project, project.getLanguageService().getSuggestionDiagnostics(file), "suggestionDiag");
                ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
            };
            Session.prototype.sendDiagnosticsEvent = function (file, project, diagnostics, kind) {
                try {
                    this.event({ file: file, diagnostics: diagnostics.map(function (diag) { return formatDiag(file, project, diag); }) }, kind);
                }
                catch (err) {
                    this.logError(err, kind);
                }
            };
            /** It is the caller's responsibility to verify that `!this.suppressDiagnosticEvents`. */
            Session.prototype.updateErrorCheck = function (next, checkList, ms, requireOpen) {
                var _this = this;
                if (requireOpen === void 0) { requireOpen = true; }
                ts.Debug.assert(!this.suppressDiagnosticEvents); // Caller's responsibility
                var seq = this.changeSeq;
                var followMs = Math.min(ms, 200);
                var index = 0;
                var goNext = function () {
                    index++;
                    if (checkList.length > index) {
                        next.delay(followMs, checkOne);
                    }
                };
                var checkOne = function () {
                    if (_this.changeSeq !== seq) {
                        return;
                    }
                    var item = checkList[index];
                    if (ts.isString(item)) {
                        // Find out project for the file name
                        item = _this.toPendingErrorCheck(item);
                        if (!item) {
                            // Ignore file if there is no project for the file
                            goNext();
                            return;
                        }
                    }
                    var fileName = item.fileName, project = item.project;
                    // Ensure the project is up to date before checking if this file is present in the project.
                    server.updateProjectIfDirty(project);
                    if (!project.containsFile(fileName, requireOpen)) {
                        return;
                    }
                    _this.syntacticCheck(fileName, project);
                    if (_this.changeSeq !== seq) {
                        return;
                    }
                    // Don't provide semantic diagnostics unless we're in full semantic mode.
                    if (project.projectService.serverMode !== ts.LanguageServiceMode.Semantic) {
                        goNext();
                        return;
                    }
                    next.immediate(function () {
                        _this.semanticCheck(fileName, project);
                        if (_this.changeSeq !== seq) {
                            return;
                        }
                        if (_this.getPreferences(fileName).disableSuggestions) {
                            goNext();
                            return;
                        }
                        next.immediate(function () {
                            _this.suggestionCheck(fileName, project);
                            goNext();
                        });
                    });
                };
                if (checkList.length > index && this.changeSeq === seq) {
                    next.delay(ms, checkOne);
                }
            };
            Session.prototype.cleanProjects = function (caption, projects) {
                if (!projects) {
                    return;
                }
                this.logger.info("cleaning ".concat(caption));
                for (var _i = 0, projects_4 = projects; _i < projects_4.length; _i++) {
                    var p = projects_4[_i];
                    p.getLanguageService(/*ensureSynchronized*/ false).cleanupSemanticCache();
                }
            };
            Session.prototype.cleanup = function () {
                this.cleanProjects("inferred projects", this.projectService.inferredProjects);
                this.cleanProjects("configured projects", ts.arrayFrom(this.projectService.configuredProjects.values()));
                this.cleanProjects("external projects", this.projectService.externalProjects);
                if (this.host.gc) {
                    this.logger.info("host.gc()");
                    this.host.gc();
                }
            };
            Session.prototype.getEncodedSyntacticClassifications = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                return languageService.getEncodedSyntacticClassifications(file, args);
            };
            Session.prototype.getEncodedSemanticClassifications = function (args) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var format = args.format === "2020" ? "2020" /* SemanticClassificationFormat.TwentyTwenty */ : "original" /* SemanticClassificationFormat.Original */;
                return project.getLanguageService().getEncodedSemanticClassifications(file, args, format);
            };
            Session.prototype.getProject = function (projectFileName) {
                return projectFileName === undefined ? undefined : this.projectService.findProject(projectFileName);
            };
            Session.prototype.getConfigFileAndProject = function (args) {
                var project = this.getProject(args.projectFileName);
                var file = server.toNormalizedPath(args.file);
                return {
                    configFile: project && project.hasConfigFile(file) ? file : undefined,
                    project: project
                };
            };
            Session.prototype.getConfigFileDiagnostics = function (configFile, project, includeLinePosition) {
                var projectErrors = project.getAllProjectErrors();
                var optionsErrors = project.getLanguageService().getCompilerOptionsDiagnostics();
                var diagnosticsForConfigFile = ts.filter(ts.concatenate(projectErrors, optionsErrors), function (diagnostic) { return !!diagnostic.file && diagnostic.file.fileName === configFile; });
                return includeLinePosition ?
                    this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnosticsForConfigFile) :
                    ts.map(diagnosticsForConfigFile, function (diagnostic) { return formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ false); });
            };
            Session.prototype.convertToDiagnosticsWithLinePositionFromDiagnosticFile = function (diagnostics) {
                var _this = this;
                return diagnostics.map(function (d) { return ({
                    message: ts.flattenDiagnosticMessageText(d.messageText, _this.host.newLine),
                    start: d.start,
                    length: d.length,
                    category: ts.diagnosticCategoryName(d),
                    code: d.code,
                    source: d.source,
                    startLocation: (d.file && convertToLocation(ts.getLineAndCharacterOfPosition(d.file, d.start))),
                    endLocation: (d.file && convertToLocation(ts.getLineAndCharacterOfPosition(d.file, d.start + d.length))),
                    reportsUnnecessary: d.reportsUnnecessary,
                    reportsDeprecated: d.reportsDeprecated,
                    relatedInformation: ts.map(d.relatedInformation, formatRelatedInformation)
                }); });
            };
            Session.prototype.getCompilerOptionsDiagnostics = function (args) {
                var project = this.getProject(args.projectFileName);
                // Get diagnostics that dont have associated file with them
                // The diagnostics which have file would be in config file and
                // would be reported as part of configFileDiagnostics
                return this.convertToDiagnosticsWithLinePosition(ts.filter(project.getLanguageService().getCompilerOptionsDiagnostics(), function (diagnostic) { return !diagnostic.file; }), 
                /*scriptInfo*/ undefined);
            };
            Session.prototype.convertToDiagnosticsWithLinePosition = function (diagnostics, scriptInfo) {
                var _this = this;
                return diagnostics.map(function (d) { return ({
                    message: ts.flattenDiagnosticMessageText(d.messageText, _this.host.newLine),
                    start: d.start,
                    length: d.length,
                    category: ts.diagnosticCategoryName(d),
                    code: d.code,
                    source: d.source,
                    startLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start),
                    endLocation: scriptInfo && scriptInfo.positionToLineOffset(d.start + d.length),
                    reportsUnnecessary: d.reportsUnnecessary,
                    reportsDeprecated: d.reportsDeprecated,
                    relatedInformation: ts.map(d.relatedInformation, formatRelatedInformation),
                }); });
            };
            Session.prototype.getDiagnosticsWorker = function (args, isSemantic, selector, includeLinePosition) {
                var _a = this.getFileAndProject(args), project = _a.project, file = _a.file;
                if (isSemantic && isDeclarationFileInJSOnlyNonConfiguredProject(project, file)) {
                    return server.emptyArray;
                }
                var scriptInfo = project.getScriptInfoForNormalizedPath(file);
                var diagnostics = selector(project, file);
                return includeLinePosition
                    ? this.convertToDiagnosticsWithLinePosition(diagnostics, scriptInfo)
                    : diagnostics.map(function (d) { return formatDiag(file, project, d); });
            };
            Session.prototype.getDefinition = function (args, simplifiedResult) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var position = this.getPositionInFile(args, file);
                var definitions = this.mapDefinitionInfoLocations(project.getLanguageService().getDefinitionAtPosition(file, position) || server.emptyArray, project);
                return simplifiedResult ? this.mapDefinitionInfo(definitions, project) : definitions.map(Session.mapToOriginalLocation);
            };
            Session.prototype.mapDefinitionInfoLocations = function (definitions, project) {
                return definitions.map(function (info) {
                    var newDocumentSpan = getMappedDocumentSpan(info, project);
                    return !newDocumentSpan ? info : __assign(__assign(__assign({}, newDocumentSpan), { containerKind: info.containerKind, containerName: info.containerName, kind: info.kind, name: info.name, failedAliasResolution: info.failedAliasResolution }), info.unverified && { unverified: info.unverified });
                });
            };
            Session.prototype.getDefinitionAndBoundSpan = function (args, simplifiedResult) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var position = this.getPositionInFile(args, file);
                var scriptInfo = ts.Debug.checkDefined(project.getScriptInfo(file));
                var unmappedDefinitionAndBoundSpan = project.getLanguageService().getDefinitionAndBoundSpan(file, position);
                if (!unmappedDefinitionAndBoundSpan || !unmappedDefinitionAndBoundSpan.definitions) {
                    return {
                        definitions: server.emptyArray,
                        textSpan: undefined // TODO: GH#18217
                    };
                }
                var definitions = this.mapDefinitionInfoLocations(unmappedDefinitionAndBoundSpan.definitions, project);
                var textSpan = unmappedDefinitionAndBoundSpan.textSpan;
                if (simplifiedResult) {
                    return {
                        definitions: this.mapDefinitionInfo(definitions, project),
                        textSpan: toProtocolTextSpan(textSpan, scriptInfo)
                    };
                }
                return {
                    definitions: definitions.map(Session.mapToOriginalLocation),
                    textSpan: textSpan,
                };
            };
            Session.prototype.findSourceDefinition = function (args) {
                var _a;
                var _b = this.getFileAndProject(args), file = _b.file, project = _b.project;
                var position = this.getPositionInFile(args, file);
                var unmappedDefinitions = project.getLanguageService().getDefinitionAtPosition(file, position);
                var definitions = this.mapDefinitionInfoLocations(unmappedDefinitions || server.emptyArray, project).slice();
                var needsJsResolution = this.projectService.serverMode === ts.LanguageServiceMode.Semantic && (!ts.some(definitions, function (d) { return server.toNormalizedPath(d.fileName) !== file && !d.isAmbient; }) ||
                    ts.some(definitions, function (d) { return !!d.failedAliasResolution; }));
                if (needsJsResolution) {
                    var definitionSet_1 = ts.createSet(function (d) { return d.textSpan.start; }, ts.documentSpansEqual);
                    definitions === null || definitions === void 0 ? void 0 : definitions.forEach(function (d) { return definitionSet_1.add(d); });
                    var noDtsProject = project.getNoDtsResolutionProject([file]);
                    var ls = noDtsProject.getLanguageService();
                    var jsDefinitions = (_a = ls.getDefinitionAtPosition(file, position, /*searchOtherFilesOnly*/ true, /*stopAtAlias*/ false)) === null || _a === void 0 ? void 0 : _a.filter(function (d) { return server.toNormalizedPath(d.fileName) !== file; });
                    if (ts.some(jsDefinitions)) {
                        for (var _i = 0, jsDefinitions_1 = jsDefinitions; _i < jsDefinitions_1.length; _i++) {
                            var jsDefinition = jsDefinitions_1[_i];
                            if (jsDefinition.unverified) {
                                var refined = tryRefineDefinition(jsDefinition, project.getLanguageService().getProgram(), ls.getProgram());
                                if (ts.some(refined)) {
                                    for (var _c = 0, refined_1 = refined; _c < refined_1.length; _c++) {
                                        var def = refined_1[_c];
                                        definitionSet_1.add(def);
                                    }
                                    continue;
                                }
                            }
                            definitionSet_1.add(jsDefinition);
                        }
                    }
                    else {
                        var ambientCandidates = definitions.filter(function (d) { return server.toNormalizedPath(d.fileName) !== file && d.isAmbient; });
                        for (var _d = 0, _e = ts.some(ambientCandidates) ? ambientCandidates : getAmbientCandidatesByClimbingAccessChain(); _d < _e.length; _d++) {
                            var candidate = _e[_d];
                            var fileNameToSearch = findImplementationFileFromDtsFileName(candidate.fileName, file, noDtsProject);
                            if (!fileNameToSearch || !ensureRoot(noDtsProject, fileNameToSearch)) {
                                continue;
                            }
                            var noDtsProgram = ls.getProgram();
                            var fileToSearch = ts.Debug.checkDefined(noDtsProgram.getSourceFile(fileNameToSearch));
                            for (var _f = 0, _g = searchForDeclaration(candidate.name, fileToSearch, noDtsProgram); _f < _g.length; _f++) {
                                var match = _g[_f];
                                definitionSet_1.add(match);
                            }
                        }
                    }
                    definitions = ts.arrayFrom(definitionSet_1.values());
                }
                definitions = definitions.filter(function (d) { return !d.isAmbient && !d.failedAliasResolution; });
                return this.mapDefinitionInfo(definitions, project);
                function findImplementationFileFromDtsFileName(fileName, resolveFromFile, auxiliaryProject) {
                    var _a;
                    var nodeModulesPathParts = ts.getNodeModulePathParts(fileName);
                    if (nodeModulesPathParts && fileName.lastIndexOf(ts.nodeModulesPathPart) === nodeModulesPathParts.topLevelNodeModulesIndex) {
                        // Second check ensures the fileName only contains one `/node_modules/`. If there's more than one I give up.
                        var packageDirectory = fileName.substring(0, nodeModulesPathParts.packageRootIndex);
                        var packageJsonCache = (_a = project.getModuleResolutionCache()) === null || _a === void 0 ? void 0 : _a.getPackageJsonInfoCache();
                        var compilerOptions = project.getCompilationSettings();
                        var packageJson = ts.getPackageScopeForPath(project.toPath(packageDirectory + "/package.json"), packageJsonCache, project, compilerOptions);
                        if (!packageJson)
                            return undefined;
                        // Use fake options instead of actual compiler options to avoid following export map if the project uses node16 or nodenext -
                        // Mapping from an export map entry across packages is out of scope for now. Returned entrypoints will only be what can be
                        // resolved from the package root under --moduleResolution node
                        var entrypoints = ts.getEntrypointsFromPackageJsonInfo(packageJson, { moduleResolution: ts.ModuleResolutionKind.NodeJs }, project, project.getModuleResolutionCache());
                        // This substring is correct only because we checked for a single `/node_modules/` at the top.
                        var packageNamePathPart = fileName.substring(nodeModulesPathParts.topLevelPackageNameIndex + 1, nodeModulesPathParts.packageRootIndex);
                        var packageName = ts.getPackageNameFromTypesPackageName(ts.unmangleScopedPackageName(packageNamePathPart));
                        var path_1 = project.toPath(fileName);
                        if (entrypoints && ts.some(entrypoints, function (e) { return project.toPath(e) === path_1; })) {
                            // This file was the main entrypoint of a package. Try to resolve that same package name with
                            // the auxiliary project that only resolves to implementation files.
                            var implementationResolution = auxiliaryProject.resolveModuleNames([packageName], resolveFromFile)[0];
                            return implementationResolution === null || implementationResolution === void 0 ? void 0 : implementationResolution.resolvedFileName;
                        }
                        else {
                            // It wasn't the main entrypoint but we are in node_modules. Try a subpath into the package.
                            var pathToFileInPackage = fileName.substring(nodeModulesPathParts.packageRootIndex + 1);
                            var specifier = "".concat(packageName, "/").concat(ts.removeFileExtension(pathToFileInPackage));
                            var implementationResolution = auxiliaryProject.resolveModuleNames([specifier], resolveFromFile)[0];
                            return implementationResolution === null || implementationResolution === void 0 ? void 0 : implementationResolution.resolvedFileName;
                        }
                    }
                    // We're not in node_modules, and we only get to this function if non-dts module resolution failed.
                    // I'm not sure what else I can do here that isn't already covered by that module resolution.
                    return undefined;
                }
                // In 'foo.bar./**/baz', if we got not results on 'baz', see if we can get an ambient definition
                // for 'bar' or 'foo' (in that order) so we can search for declarations of 'baz' later.
                function getAmbientCandidatesByClimbingAccessChain() {
                    var ls = project.getLanguageService();
                    var program = ls.getProgram();
                    var initialNode = ts.getTouchingPropertyName(program.getSourceFile(file), position);
                    if ((ts.isStringLiteralLike(initialNode) || ts.isIdentifier(initialNode)) && ts.isAccessExpression(initialNode.parent)) {
                        return ts.forEachNameInAccessChainWalkingLeft(initialNode, function (nameInChain) {
                            var _a;
                            if (nameInChain === initialNode)
                                return undefined;
                            var candidates = (_a = ls.getDefinitionAtPosition(file, nameInChain.getStart(), /*searchOtherFilesOnly*/ true, /*stopAtAlias*/ false)) === null || _a === void 0 ? void 0 : _a.filter(function (d) { return server.toNormalizedPath(d.fileName) !== file && d.isAmbient; }).map(function (d) { return ({
                                fileName: d.fileName,
                                name: ts.getTextOfIdentifierOrLiteral(initialNode)
                            }); });
                            if (ts.some(candidates)) {
                                return candidates;
                            }
                        }) || server.emptyArray;
                    }
                    return server.emptyArray;
                }
                function tryRefineDefinition(definition, program, noDtsProgram) {
                    var _a;
                    var fileToSearch = noDtsProgram.getSourceFile(definition.fileName);
                    if (!fileToSearch) {
                        return undefined;
                    }
                    var initialNode = ts.getTouchingPropertyName(program.getSourceFile(file), position);
                    var symbol = program.getTypeChecker().getSymbolAtLocation(initialNode);
                    var importSpecifier = symbol && ts.getDeclarationOfKind(symbol, 270 /* SyntaxKind.ImportSpecifier */);
                    if (!importSpecifier)
                        return undefined;
                    var nameToSearch = ((_a = importSpecifier.propertyName) === null || _a === void 0 ? void 0 : _a.text) || importSpecifier.name.text;
                    return searchForDeclaration(nameToSearch, fileToSearch, noDtsProgram);
                }
                function searchForDeclaration(declarationName, fileToSearch, noDtsProgram) {
                    var matches = ts.FindAllReferences.Core.getTopMostDeclarationNamesInFile(declarationName, fileToSearch);
                    return ts.mapDefined(matches, function (match) {
                        var symbol = noDtsProgram.getTypeChecker().getSymbolAtLocation(match);
                        var decl = ts.getDeclarationFromName(match);
                        if (symbol && decl) {
                            // I think the last argument to this is supposed to be the start node, but it doesn't seem important.
                            // Callers internal to GoToDefinition already get confused about this.
                            return ts.GoToDefinition.createDefinitionInfo(decl, noDtsProgram.getTypeChecker(), symbol, decl, /*unverified*/ true);
                        }
                    });
                }
                function ensureRoot(project, fileName) {
                    var info = project.getScriptInfo(fileName);
                    if (!info)
                        return false;
                    if (!project.containsScriptInfo(info)) {
                        project.addRoot(info);
                        project.updateGraph();
                    }
                    return true;
                }
            };
            Session.prototype.getEmitOutput = function (args) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                if (!project.shouldEmitFile(project.getScriptInfo(file))) {
                    return { emitSkipped: true, outputFiles: [], diagnostics: [] };
                }
                var result = project.getLanguageService().getEmitOutput(file);
                return args.richResponse ? __assign(__assign({}, result), { diagnostics: args.includeLinePosition ?
                        this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(result.diagnostics) :
                        result.diagnostics.map(function (d) { return formatDiagnosticToProtocol(d, /*includeFileName*/ true); }) }) :
                    result;
            };
            Session.prototype.mapJSDocTagInfo = function (tags, project, richResponse) {
                var _this = this;
                return tags ? tags.map(function (tag) {
                    var _a;
                    return (__assign(__assign({}, tag), { text: richResponse ? _this.mapDisplayParts(tag.text, project) : (_a = tag.text) === null || _a === void 0 ? void 0 : _a.map(function (part) { return part.text; }).join("") }));
                }) : [];
            };
            Session.prototype.mapDisplayParts = function (parts, project) {
                var _this = this;
                if (!parts) {
                    return [];
                }
                return parts.map(function (part) { return part.kind !== "linkName" ? part : __assign(__assign({}, part), { target: _this.toFileSpan(part.target.fileName, part.target.textSpan, project) }); });
            };
            Session.prototype.mapSignatureHelpItems = function (items, project, richResponse) {
                var _this = this;
                return items.map(function (item) { return (__assign(__assign({}, item), { documentation: _this.mapDisplayParts(item.documentation, project), parameters: item.parameters.map(function (p) { return (__assign(__assign({}, p), { documentation: _this.mapDisplayParts(p.documentation, project) })); }), tags: _this.mapJSDocTagInfo(item.tags, project, richResponse) })); });
            };
            Session.prototype.mapDefinitionInfo = function (definitions, project) {
                var _this = this;
                return definitions.map(function (def) { return (__assign(__assign({}, _this.toFileSpanWithContext(def.fileName, def.textSpan, def.contextSpan, project)), def.unverified && { unverified: def.unverified })); });
            };
            /*
             * When we map a .d.ts location to .ts, Visual Studio gets confused because there's no associated Roslyn Document in
             * the same project which corresponds to the file. VS Code has no problem with this, and luckily we have two protocols.
             * This retains the existing behavior for the "simplified" (VS Code) protocol but stores the .d.ts location in a
             * set of additional fields, and does the reverse for VS (store the .d.ts location where
             * it used to be and stores the .ts location in the additional fields).
            */
            Session.mapToOriginalLocation = function (def) {
                if (def.originalFileName) {
                    ts.Debug.assert(def.originalTextSpan !== undefined, "originalTextSpan should be present if originalFileName is");
                    return __assign(__assign({}, def), { fileName: def.originalFileName, textSpan: def.originalTextSpan, targetFileName: def.fileName, targetTextSpan: def.textSpan, contextSpan: def.originalContextSpan, targetContextSpan: def.contextSpan });
                }
                return def;
            };
            Session.prototype.toFileSpan = function (fileName, textSpan, project) {
                var ls = project.getLanguageService();
                var start = ls.toLineColumnOffset(fileName, textSpan.start); // TODO: GH#18217
                var end = ls.toLineColumnOffset(fileName, ts.textSpanEnd(textSpan));
                return {
                    file: fileName,
                    start: { line: start.line + 1, offset: start.character + 1 },
                    end: { line: end.line + 1, offset: end.character + 1 }
                };
            };
            Session.prototype.toFileSpanWithContext = function (fileName, textSpan, contextSpan, project) {
                var fileSpan = this.toFileSpan(fileName, textSpan, project);
                var context = contextSpan && this.toFileSpan(fileName, contextSpan, project);
                return context ? __assign(__assign({}, fileSpan), { contextStart: context.start, contextEnd: context.end }) :
                    fileSpan;
            };
            Session.prototype.getTypeDefinition = function (args) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var position = this.getPositionInFile(args, file);
                var definitions = this.mapDefinitionInfoLocations(project.getLanguageService().getTypeDefinitionAtPosition(file, position) || server.emptyArray, project);
                return this.mapDefinitionInfo(definitions, project);
            };
            Session.prototype.mapImplementationLocations = function (implementations, project) {
                return implementations.map(function (info) {
                    var newDocumentSpan = getMappedDocumentSpan(info, project);
                    return !newDocumentSpan ? info : __assign(__assign({}, newDocumentSpan), { kind: info.kind, displayParts: info.displayParts });
                });
            };
            Session.prototype.getImplementation = function (args, simplifiedResult) {
                var _this = this;
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var position = this.getPositionInFile(args, file);
                var implementations = this.mapImplementationLocations(project.getLanguageService().getImplementationAtPosition(file, position) || server.emptyArray, project);
                return simplifiedResult ?
                    implementations.map(function (_a) {
                        var fileName = _a.fileName, textSpan = _a.textSpan, contextSpan = _a.contextSpan;
                        return _this.toFileSpanWithContext(fileName, textSpan, contextSpan, project);
                    }) :
                    implementations.map(Session.mapToOriginalLocation);
            };
            Session.prototype.getOccurrences = function (args) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var position = this.getPositionInFile(args, file);
                var occurrences = project.getLanguageService().getOccurrencesAtPosition(file, position);
                return occurrences ?
                    occurrences.map(function (occurrence) {
                        var fileName = occurrence.fileName, isWriteAccess = occurrence.isWriteAccess, textSpan = occurrence.textSpan, isInString = occurrence.isInString, contextSpan = occurrence.contextSpan;
                        var scriptInfo = project.getScriptInfo(fileName);
                        return __assign(__assign(__assign({}, toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo)), { file: fileName, isWriteAccess: isWriteAccess }), (isInString ? { isInString: isInString } : undefined));
                    }) :
                    server.emptyArray;
            };
            Session.prototype.getSyntacticDiagnosticsSync = function (args) {
                var configFile = this.getConfigFileAndProject(args).configFile;
                if (configFile) {
                    // all the config file errors are reported as part of semantic check so nothing to report here
                    return server.emptyArray;
                }
                return this.getDiagnosticsWorker(args, /*isSemantic*/ false, function (project, file) { return project.getLanguageService().getSyntacticDiagnostics(file); }, !!args.includeLinePosition);
            };
            Session.prototype.getSemanticDiagnosticsSync = function (args) {
                var _a = this.getConfigFileAndProject(args), configFile = _a.configFile, project = _a.project;
                if (configFile) {
                    return this.getConfigFileDiagnostics(configFile, project, !!args.includeLinePosition); // TODO: GH#18217
                }
                return this.getDiagnosticsWorker(args, /*isSemantic*/ true, function (project, file) { return project.getLanguageService().getSemanticDiagnostics(file).filter(function (d) { return !!d.file; }); }, !!args.includeLinePosition);
            };
            Session.prototype.getSuggestionDiagnosticsSync = function (args) {
                var configFile = this.getConfigFileAndProject(args).configFile;
                if (configFile) {
                    // Currently there are no info diagnostics for config files.
                    return server.emptyArray;
                }
                // isSemantic because we don't want to info diagnostics in declaration files for JS-only users
                return this.getDiagnosticsWorker(args, /*isSemantic*/ true, function (project, file) { return project.getLanguageService().getSuggestionDiagnostics(file); }, !!args.includeLinePosition);
            };
            Session.prototype.getJsxClosingTag = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var position = this.getPositionInFile(args, file);
                var tag = languageService.getJsxClosingTagAtPosition(file, position);
                return tag === undefined ? undefined : { newText: tag.newText, caretOffset: 0 };
            };
            Session.prototype.getDocumentHighlights = function (args, simplifiedResult) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var position = this.getPositionInFile(args, file);
                var documentHighlights = project.getLanguageService().getDocumentHighlights(file, position, args.filesToSearch);
                if (!documentHighlights)
                    return server.emptyArray;
                if (!simplifiedResult)
                    return documentHighlights;
                return documentHighlights.map(function (_a) {
                    var fileName = _a.fileName, highlightSpans = _a.highlightSpans;
                    var scriptInfo = project.getScriptInfo(fileName);
                    return {
                        file: fileName,
                        highlightSpans: highlightSpans.map(function (_a) {
                            var textSpan = _a.textSpan, kind = _a.kind, contextSpan = _a.contextSpan;
                            return (__assign(__assign({}, toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo)), { kind: kind }));
                        })
                    };
                });
            };
            Session.prototype.provideInlayHints = function (args) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var hints = project.getLanguageService().provideInlayHints(file, args, this.getPreferences(file));
                return hints.map(function (hint) { return (__assign(__assign({}, hint), { position: scriptInfo.positionToLineOffset(hint.position) })); });
            };
            Session.prototype.setCompilerOptionsForInferredProjects = function (args) {
                this.projectService.setCompilerOptionsForInferredProjects(args.options, args.projectRootPath);
            };
            Session.prototype.getProjectInfo = function (args) {
                return this.getProjectInfoWorker(args.file, args.projectFileName, args.needFileNameList, /*excludeConfigFiles*/ false);
            };
            Session.prototype.getProjectInfoWorker = function (uncheckedFileName, projectFileName, needFileNameList, excludeConfigFiles) {
                var project = this.getFileAndProjectWorker(uncheckedFileName, projectFileName).project;
                server.updateProjectIfDirty(project);
                var projectInfo = {
                    configFileName: project.getProjectName(),
                    languageServiceDisabled: !project.languageServiceEnabled,
                    fileNames: needFileNameList ? project.getFileNames(/*excludeFilesFromExternalLibraries*/ false, excludeConfigFiles) : undefined
                };
                return projectInfo;
            };
            Session.prototype.getRenameInfo = function (args) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var position = this.getPositionInFile(args, file);
                return project.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getPreferences(file).allowRenameOfImportPath });
            };
            Session.prototype.getProjects = function (args, getScriptInfoEnsuringProjectsUptoDate, ignoreNoProjectError) {
                var _a;
                var projects;
                var symLinkedProjects;
                if (args.projectFileName) {
                    var project = this.getProject(args.projectFileName);
                    if (project) {
                        projects = [project];
                    }
                }
                else {
                    var scriptInfo = getScriptInfoEnsuringProjectsUptoDate ?
                        this.projectService.getScriptInfoEnsuringProjectsUptoDate(args.file) :
                        this.projectService.getScriptInfo(args.file);
                    if (!scriptInfo) {
                        if (ignoreNoProjectError)
                            return server.emptyArray;
                        this.projectService.logErrorForScriptInfoNotFound(args.file);
                        return server.Errors.ThrowNoProject();
                    }
                    projects = scriptInfo.containingProjects;
                    symLinkedProjects = this.projectService.getSymlinkedProjects(scriptInfo);
                }
                // filter handles case when 'projects' is undefined
                projects = ts.filter(projects, function (p) { return p.languageServiceEnabled && !p.isOrphan(); });
                if (!ignoreNoProjectError && (!projects || !projects.length) && !symLinkedProjects) {
                    this.projectService.logErrorForScriptInfoNotFound((_a = args.file) !== null && _a !== void 0 ? _a : args.projectFileName);
                    return server.Errors.ThrowNoProject();
                }
                return symLinkedProjects ? { projects: projects, symLinkedProjects: symLinkedProjects } : projects; // TODO: GH#18217
            };
            Session.prototype.getDefaultProject = function (args) {
                if (args.projectFileName) {
                    var project = this.getProject(args.projectFileName);
                    if (project) {
                        return project;
                    }
                    if (!args.file) {
                        return server.Errors.ThrowNoProject();
                    }
                }
                var info = this.projectService.getScriptInfo(args.file);
                return info.getDefaultProject();
            };
            Session.prototype.getRenameLocations = function (args, simplifiedResult) {
                var file = server.toNormalizedPath(args.file);
                var position = this.getPositionInFile(args, file);
                var projects = this.getProjects(args);
                var defaultProject = this.getDefaultProject(args);
                var renameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getPreferences(file).allowRenameOfImportPath }), ts.Debug.checkDefined(this.projectService.getScriptInfo(file)));
                if (!renameInfo.canRename)
                    return simplifiedResult ? { info: renameInfo, locs: [] } : [];
                var locations = combineProjectOutputForRenameLocations(projects, defaultProject, { fileName: args.file, pos: position }, !!args.findInStrings, !!args.findInComments, this.getPreferences(file));
                if (!simplifiedResult)
                    return locations;
                return { info: renameInfo, locs: this.toSpanGroups(locations) };
            };
            Session.prototype.mapRenameInfo = function (info, scriptInfo) {
                if (info.canRename) {
                    var canRename = info.canRename, fileToRename = info.fileToRename, displayName = info.displayName, fullDisplayName = info.fullDisplayName, kind = info.kind, kindModifiers = info.kindModifiers, triggerSpan = info.triggerSpan;
                    return ts.identity({ canRename: canRename, fileToRename: fileToRename, displayName: displayName, fullDisplayName: fullDisplayName, kind: kind, kindModifiers: kindModifiers, triggerSpan: toProtocolTextSpan(triggerSpan, scriptInfo) });
                }
                else {
                    return info;
                }
            };
            Session.prototype.toSpanGroups = function (locations) {
                var map = new ts.Map();
                for (var _i = 0, locations_1 = locations; _i < locations_1.length; _i++) {
                    var _a = locations_1[_i];
                    var fileName = _a.fileName, textSpan = _a.textSpan, contextSpan = _a.contextSpan, _2 = _a.originalContextSpan, _ = _a.originalTextSpan, _1 = _a.originalFileName, prefixSuffixText = __rest(_a, ["fileName", "textSpan", "contextSpan", "originalContextSpan", "originalTextSpan", "originalFileName"]);
                    var group_1 = map.get(fileName);
                    if (!group_1)
                        map.set(fileName, group_1 = { file: fileName, locs: [] });
                    var scriptInfo = ts.Debug.checkDefined(this.projectService.getScriptInfo(fileName));
                    group_1.locs.push(__assign(__assign({}, toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo)), prefixSuffixText));
                }
                return ts.arrayFrom(map.values());
            };
            Session.prototype.getReferences = function (args, simplifiedResult) {
                var _this = this;
                var file = server.toNormalizedPath(args.file);
                var projects = this.getProjects(args);
                var position = this.getPositionInFile(args, file);
                var references = combineProjectOutputForReferences(projects, this.getDefaultProject(args), { fileName: args.file, pos: position }, this.logger);
                if (!simplifiedResult)
                    return references;
                var defaultProject = this.getDefaultProject(args);
                var scriptInfo = defaultProject.getScriptInfoForNormalizedPath(file);
                var nameInfo = defaultProject.getLanguageService().getQuickInfoAtPosition(file, position);
                var symbolDisplayString = nameInfo ? ts.displayPartsToString(nameInfo.displayParts) : "";
                var nameSpan = nameInfo && nameInfo.textSpan;
                var symbolStartOffset = nameSpan ? scriptInfo.positionToLineOffset(nameSpan.start).offset : 0;
                var symbolName = nameSpan ? scriptInfo.getSnapshot().getText(nameSpan.start, ts.textSpanEnd(nameSpan)) : "";
                var refs = ts.flatMap(references, function (referencedSymbol) {
                    return referencedSymbol.references.map(function (entry) { return referenceEntryToReferencesResponseItem(_this.projectService, entry); });
                });
                return { refs: refs, symbolName: symbolName, symbolStartOffset: symbolStartOffset, symbolDisplayString: symbolDisplayString };
            };
            Session.prototype.getFileReferences = function (args, simplifiedResult) {
                var _this = this;
                var projects = this.getProjects(args);
                var fileName = args.file;
                var references = [];
                var seen = createDocumentSpanSet();
                forEachProjectInProjects(projects, /*path*/ undefined, function (project) {
                    if (project.getCancellationToken().isCancellationRequested())
                        return;
                    var projectOutputs = project.getLanguageService().getFileReferences(fileName);
                    if (projectOutputs) {
                        for (var _i = 0, projectOutputs_3 = projectOutputs; _i < projectOutputs_3.length; _i++) {
                            var referenceEntry = projectOutputs_3[_i];
                            if (!seen.has(referenceEntry)) {
                                references.push(referenceEntry);
                                seen.add(referenceEntry);
                            }
                        }
                    }
                });
                if (!simplifiedResult)
                    return references;
                var refs = references.map(function (entry) { return referenceEntryToReferencesResponseItem(_this.projectService, entry); });
                return {
                    refs: refs,
                    symbolName: "\"".concat(args.file, "\"")
                };
            };
            /**
             * @param fileName is the name of the file to be opened
             * @param fileContent is a version of the file content that is known to be more up to date than the one on disk
             */
            Session.prototype.openClientFile = function (fileName, fileContent, scriptKind, projectRootPath) {
                this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath);
            };
            Session.prototype.getPosition = function (args, scriptInfo) {
                return args.position !== undefined ? args.position : scriptInfo.lineOffsetToPosition(args.line, args.offset);
            };
            Session.prototype.getPositionInFile = function (args, file) {
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                return this.getPosition(args, scriptInfo);
            };
            Session.prototype.getFileAndProject = function (args) {
                return this.getFileAndProjectWorker(args.file, args.projectFileName);
            };
            Session.prototype.getFileAndLanguageServiceForSyntacticOperation = function (args) {
                // Since this is syntactic operation, there should always be project for the file
                // we wouldnt have to ensure project but rather throw if we dont get project
                var file = server.toNormalizedPath(args.file);
                var project = this.getProject(args.projectFileName) || this.projectService.tryGetDefaultProjectForFile(file);
                if (!project) {
                    return server.Errors.ThrowNoProject();
                }
                return {
                    file: file,
                    languageService: project.getLanguageService(/*ensureSynchronized*/ false)
                };
            };
            Session.prototype.getFileAndProjectWorker = function (uncheckedFileName, projectFileName) {
                var file = server.toNormalizedPath(uncheckedFileName);
                var project = this.getProject(projectFileName) || this.projectService.ensureDefaultProjectForFile(file);
                return { file: file, project: project };
            };
            Session.prototype.getOutliningSpans = function (args, simplifiedResult) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var spans = languageService.getOutliningSpans(file);
                if (simplifiedResult) {
                    var scriptInfo_1 = this.projectService.getScriptInfoForNormalizedPath(file);
                    return spans.map(function (s) { return ({
                        textSpan: toProtocolTextSpan(s.textSpan, scriptInfo_1),
                        hintSpan: toProtocolTextSpan(s.hintSpan, scriptInfo_1),
                        bannerText: s.bannerText,
                        autoCollapse: s.autoCollapse,
                        kind: s.kind
                    }); });
                }
                else {
                    return spans;
                }
            };
            Session.prototype.getTodoComments = function (args) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                return project.getLanguageService().getTodoComments(file, args.descriptors);
            };
            Session.prototype.getDocCommentTemplate = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var position = this.getPositionInFile(args, file);
                return languageService.getDocCommentTemplateAtPosition(file, position, this.getPreferences(file));
            };
            Session.prototype.getSpanOfEnclosingComment = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var onlyMultiLine = args.onlyMultiLine;
                var position = this.getPositionInFile(args, file);
                return languageService.getSpanOfEnclosingComment(file, position, onlyMultiLine);
            };
            Session.prototype.getIndentation = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var position = this.getPositionInFile(args, file);
                var options = args.options ? server.convertFormatOptions(args.options) : this.getFormatOptions(file);
                var indentation = languageService.getIndentationAtPosition(file, position, options);
                return { position: position, indentation: indentation };
            };
            Session.prototype.getBreakpointStatement = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var position = this.getPositionInFile(args, file);
                return languageService.getBreakpointStatementAtPosition(file, position);
            };
            Session.prototype.getNameOrDottedNameSpan = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var position = this.getPositionInFile(args, file);
                return languageService.getNameOrDottedNameSpan(file, position, position);
            };
            Session.prototype.isValidBraceCompletion = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var position = this.getPositionInFile(args, file);
                return languageService.isValidBraceCompletionAtPosition(file, position, args.openingBrace.charCodeAt(0));
            };
            Session.prototype.getQuickInfoWorker = function (args, simplifiedResult) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var quickInfo = project.getLanguageService().getQuickInfoAtPosition(file, this.getPosition(args, scriptInfo));
                if (!quickInfo) {
                    return undefined;
                }
                var useDisplayParts = !!this.getPreferences(file).displayPartsForJSDoc;
                if (simplifiedResult) {
                    var displayString = ts.displayPartsToString(quickInfo.displayParts);
                    return {
                        kind: quickInfo.kind,
                        kindModifiers: quickInfo.kindModifiers,
                        start: scriptInfo.positionToLineOffset(quickInfo.textSpan.start),
                        end: scriptInfo.positionToLineOffset(ts.textSpanEnd(quickInfo.textSpan)),
                        displayString: displayString,
                        documentation: useDisplayParts ? this.mapDisplayParts(quickInfo.documentation, project) : ts.displayPartsToString(quickInfo.documentation),
                        tags: this.mapJSDocTagInfo(quickInfo.tags, project, useDisplayParts),
                    };
                }
                else {
                    return useDisplayParts ? quickInfo : __assign(__assign({}, quickInfo), { tags: this.mapJSDocTagInfo(quickInfo.tags, project, /*useDisplayParts*/ false) });
                }
            };
            Session.prototype.getFormattingEditsForRange = function (args) {
                var _this = this;
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var startPosition = scriptInfo.lineOffsetToPosition(args.line, args.offset);
                var endPosition = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset);
                // TODO: avoid duplicate code (with formatonkey)
                var edits = languageService.getFormattingEditsForRange(file, startPosition, endPosition, this.getFormatOptions(file));
                if (!edits) {
                    return undefined;
                }
                return edits.map(function (edit) { return _this.convertTextChangeToCodeEdit(edit, scriptInfo); });
            };
            Session.prototype.getFormattingEditsForRangeFull = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var options = args.options ? server.convertFormatOptions(args.options) : this.getFormatOptions(file);
                return languageService.getFormattingEditsForRange(file, args.position, args.endPosition, options); // TODO: GH#18217
            };
            Session.prototype.getFormattingEditsForDocumentFull = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var options = args.options ? server.convertFormatOptions(args.options) : this.getFormatOptions(file);
                return languageService.getFormattingEditsForDocument(file, options);
            };
            Session.prototype.getFormattingEditsAfterKeystrokeFull = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var options = args.options ? server.convertFormatOptions(args.options) : this.getFormatOptions(file);
                return languageService.getFormattingEditsAfterKeystroke(file, args.position, args.key, options); // TODO: GH#18217
            };
            Session.prototype.getFormattingEditsAfterKeystroke = function (args) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var position = scriptInfo.lineOffsetToPosition(args.line, args.offset);
                var formatOptions = this.getFormatOptions(file);
                var edits = languageService.getFormattingEditsAfterKeystroke(file, position, args.key, formatOptions);
                // Check whether we should auto-indent. This will be when
                // the position is on a line containing only whitespace.
                // This should leave the edits returned from
                // getFormattingEditsAfterKeystroke either empty or pertaining
                // only to the previous line.  If all this is true, then
                // add edits necessary to properly indent the current line.
                if ((args.key === "\n") && ((!edits) || (edits.length === 0) || allEditsBeforePos(edits, position))) {
                    var _b = scriptInfo.getAbsolutePositionAndLineText(args.line), lineText = _b.lineText, absolutePosition = _b.absolutePosition;
                    if (lineText && lineText.search("\\S") < 0) {
                        var preferredIndent = languageService.getIndentationAtPosition(file, position, formatOptions);
                        var hasIndent = 0;
                        var i = void 0, len = void 0;
                        for (i = 0, len = lineText.length; i < len; i++) {
                            if (lineText.charAt(i) === " ") {
                                hasIndent++;
                            }
                            else if (lineText.charAt(i) === "\t") {
                                hasIndent += formatOptions.tabSize; // TODO: GH#18217
                            }
                            else {
                                break;
                            }
                        }
                        // i points to the first non whitespace character
                        if (preferredIndent !== hasIndent) {
                            var firstNoWhiteSpacePosition = absolutePosition + i;
                            edits.push({
                                span: ts.createTextSpanFromBounds(absolutePosition, firstNoWhiteSpacePosition),
                                newText: ts.formatting.getIndentationString(preferredIndent, formatOptions)
                            });
                        }
                    }
                }
                if (!edits) {
                    return undefined;
                }
                return edits.map(function (edit) {
                    return {
                        start: scriptInfo.positionToLineOffset(edit.span.start),
                        end: scriptInfo.positionToLineOffset(ts.textSpanEnd(edit.span)),
                        newText: edit.newText ? edit.newText : ""
                    };
                });
            };
            Session.prototype.getCompletions = function (args, kind) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var position = this.getPosition(args, scriptInfo);
                var completions = project.getLanguageService().getCompletionsAtPosition(file, position, __assign(__assign({}, server.convertUserPreferences(this.getPreferences(file))), { triggerCharacter: args.triggerCharacter, triggerKind: args.triggerKind, includeExternalModuleExports: args.includeExternalModuleExports, includeInsertTextCompletions: args.includeInsertTextCompletions }), project.projectService.getFormatCodeOptions(file));
                if (completions === undefined)
                    return undefined;
                if (kind === "completions-full" /* protocol.CommandTypes.CompletionsFull */)
                    return completions;
                var prefix = args.prefix || "";
                var entries = ts.mapDefined(completions.entries, function (entry) {
                    if (completions.isMemberCompletion || ts.startsWith(entry.name.toLowerCase(), prefix.toLowerCase())) {
                        var name = entry.name, kind_1 = entry.kind, kindModifiers = entry.kindModifiers, sortText = entry.sortText, insertText = entry.insertText, replacementSpan = entry.replacementSpan, hasAction = entry.hasAction, source = entry.source, sourceDisplay = entry.sourceDisplay, labelDetails = entry.labelDetails, isSnippet = entry.isSnippet, isRecommended = entry.isRecommended, isPackageJsonImport = entry.isPackageJsonImport, isImportStatementCompletion = entry.isImportStatementCompletion, data = entry.data;
                        var convertedSpan = replacementSpan ? toProtocolTextSpan(replacementSpan, scriptInfo) : undefined;
                        // Use `hasAction || undefined` to avoid serializing `false`.
                        return {
                            name: name,
                            kind: kind_1,
                            kindModifiers: kindModifiers,
                            sortText: sortText,
                            insertText: insertText,
                            replacementSpan: convertedSpan,
                            isSnippet: isSnippet,
                            hasAction: hasAction || undefined,
                            source: source,
                            sourceDisplay: sourceDisplay,
                            labelDetails: labelDetails,
                            isRecommended: isRecommended,
                            isPackageJsonImport: isPackageJsonImport,
                            isImportStatementCompletion: isImportStatementCompletion,
                            data: data
                        };
                    }
                });
                if (kind === "completions" /* protocol.CommandTypes.Completions */) {
                    if (completions.metadata)
                        entries.metadata = completions.metadata;
                    return entries;
                }
                var res = __assign(__assign({}, completions), { optionalReplacementSpan: completions.optionalReplacementSpan && toProtocolTextSpan(completions.optionalReplacementSpan, scriptInfo), entries: entries });
                return res;
            };
            Session.prototype.getCompletionEntryDetails = function (args, fullResult) {
                var _this = this;
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var position = this.getPosition(args, scriptInfo);
                var formattingOptions = project.projectService.getFormatCodeOptions(file);
                var useDisplayParts = !!this.getPreferences(file).displayPartsForJSDoc;
                var result = ts.mapDefined(args.entryNames, function (entryName) {
                    var _a = typeof entryName === "string" ? { name: entryName, source: undefined, data: undefined } : entryName, name = _a.name, source = _a.source, data = _a.data;
                    return project.getLanguageService().getCompletionEntryDetails(file, position, name, formattingOptions, source, _this.getPreferences(file), data ? ts.cast(data, isCompletionEntryData) : undefined);
                });
                return fullResult
                    ? (useDisplayParts ? result : result.map(function (details) { return (__assign(__assign({}, details), { tags: _this.mapJSDocTagInfo(details.tags, project, /*richResponse*/ false) })); }))
                    : result.map(function (details) { return (__assign(__assign({}, details), { codeActions: ts.map(details.codeActions, function (action) { return _this.mapCodeAction(action); }), documentation: _this.mapDisplayParts(details.documentation, project), tags: _this.mapJSDocTagInfo(details.tags, project, useDisplayParts) })); });
            };
            Session.prototype.getCompileOnSaveAffectedFileList = function (args) {
                var _this = this;
                var projects = this.getProjects(args, /*getScriptInfoEnsuringProjectsUptoDate*/ true, /*ignoreNoProjectError*/ true);
                var info = this.projectService.getScriptInfo(args.file);
                if (!info) {
                    return server.emptyArray;
                }
                return combineProjectOutput(info, function (path) { return _this.projectService.getScriptInfoForPath(path); }, projects, function (project, info) {
                    if (!project.compileOnSaveEnabled || !project.languageServiceEnabled || project.isOrphan()) {
                        return undefined;
                    }
                    var compilationSettings = project.getCompilationSettings();
                    if (!!compilationSettings.noEmit || ts.isDeclarationFileName(info.fileName) && !dtsChangeCanAffectEmit(compilationSettings)) {
                        // avoid triggering emit when a change is made in a .d.ts when declaration emit and decorator metadata emit are disabled
                        return undefined;
                    }
                    return {
                        projectFileName: project.getProjectName(),
                        fileNames: project.getCompileOnSaveAffectedFileList(info),
                        projectUsesOutFile: !!ts.outFile(compilationSettings)
                    };
                });
            };
            Session.prototype.emitFile = function (args) {
                var _this = this;
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                if (!project) {
                    server.Errors.ThrowNoProject();
                }
                if (!project.languageServiceEnabled) {
                    return args.richResponse ? { emitSkipped: true, diagnostics: [] } : false;
                }
                var scriptInfo = project.getScriptInfo(file);
                var _b = project.emitFile(scriptInfo, function (path, data, writeByteOrderMark) { return _this.host.writeFile(path, data, writeByteOrderMark); }), emitSkipped = _b.emitSkipped, diagnostics = _b.diagnostics;
                return args.richResponse ?
                    {
                        emitSkipped: emitSkipped,
                        diagnostics: args.includeLinePosition ?
                            this.convertToDiagnosticsWithLinePositionFromDiagnosticFile(diagnostics) :
                            diagnostics.map(function (d) { return formatDiagnosticToProtocol(d, /*includeFileName*/ true); })
                    } :
                    !emitSkipped;
            };
            Session.prototype.getSignatureHelpItems = function (args, simplifiedResult) {
                var _this = this;
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var position = this.getPosition(args, scriptInfo);
                var helpItems = project.getLanguageService().getSignatureHelpItems(file, position, args);
                var useDisplayParts = !!this.getPreferences(file).displayPartsForJSDoc;
                if (helpItems && simplifiedResult) {
                    var span = helpItems.applicableSpan;
                    return __assign(__assign({}, helpItems), { applicableSpan: {
                            start: scriptInfo.positionToLineOffset(span.start),
                            end: scriptInfo.positionToLineOffset(span.start + span.length)
                        }, items: this.mapSignatureHelpItems(helpItems.items, project, useDisplayParts) });
                }
                else if (useDisplayParts || !helpItems) {
                    return helpItems;
                }
                else {
                    return __assign(__assign({}, helpItems), { items: helpItems.items.map(function (item) { return (__assign(__assign({}, item), { tags: _this.mapJSDocTagInfo(item.tags, project, /*richResponse*/ false) })); }) });
                }
            };
            Session.prototype.toPendingErrorCheck = function (uncheckedFileName) {
                var fileName = server.toNormalizedPath(uncheckedFileName);
                var project = this.projectService.tryGetDefaultProjectForFile(fileName);
                return project && { fileName: fileName, project: project };
            };
            Session.prototype.getDiagnostics = function (next, delay, fileNames) {
                if (this.suppressDiagnosticEvents) {
                    return;
                }
                if (fileNames.length > 0) {
                    this.updateErrorCheck(next, fileNames, delay);
                }
            };
            Session.prototype.change = function (args) {
                var scriptInfo = this.projectService.getScriptInfo(args.file);
                ts.Debug.assert(!!scriptInfo);
                var start = scriptInfo.lineOffsetToPosition(args.line, args.offset);
                var end = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset);
                if (start >= 0) {
                    this.changeSeq++;
                    this.projectService.applyChangesToFile(scriptInfo, ts.singleIterator({
                        span: { start: start, length: end - start },
                        newText: args.insertString // TODO: GH#18217
                    }));
                }
            };
            Session.prototype.reload = function (args, reqSeq) {
                var file = server.toNormalizedPath(args.file);
                var tempFileName = args.tmpfile === undefined ? undefined : server.toNormalizedPath(args.tmpfile);
                var info = this.projectService.getScriptInfoForNormalizedPath(file);
                if (info) {
                    this.changeSeq++;
                    // make sure no changes happen before this one is finished
                    if (info.reloadFromFile(tempFileName)) {
                        this.doOutput(/*info*/ undefined, server.CommandNames.Reload, reqSeq, /*success*/ true);
                    }
                }
            };
            Session.prototype.saveToTmp = function (fileName, tempFileName) {
                var scriptInfo = this.projectService.getScriptInfo(fileName);
                if (scriptInfo) {
                    scriptInfo.saveTo(tempFileName);
                }
            };
            Session.prototype.closeClientFile = function (fileName) {
                if (!fileName) {
                    return;
                }
                var file = ts.normalizePath(fileName);
                this.projectService.closeClientFile(file);
            };
            Session.prototype.mapLocationNavigationBarItems = function (items, scriptInfo) {
                var _this = this;
                return ts.map(items, function (item) { return ({
                    text: item.text,
                    kind: item.kind,
                    kindModifiers: item.kindModifiers,
                    spans: item.spans.map(function (span) { return toProtocolTextSpan(span, scriptInfo); }),
                    childItems: _this.mapLocationNavigationBarItems(item.childItems, scriptInfo),
                    indent: item.indent
                }); });
            };
            Session.prototype.getNavigationBarItems = function (args, simplifiedResult) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var items = languageService.getNavigationBarItems(file);
                return !items
                    ? undefined
                    : simplifiedResult
                        ? this.mapLocationNavigationBarItems(items, this.projectService.getScriptInfoForNormalizedPath(file))
                        : items;
            };
            Session.prototype.toLocationNavigationTree = function (tree, scriptInfo) {
                var _this = this;
                return {
                    text: tree.text,
                    kind: tree.kind,
                    kindModifiers: tree.kindModifiers,
                    spans: tree.spans.map(function (span) { return toProtocolTextSpan(span, scriptInfo); }),
                    nameSpan: tree.nameSpan && toProtocolTextSpan(tree.nameSpan, scriptInfo),
                    childItems: ts.map(tree.childItems, function (item) { return _this.toLocationNavigationTree(item, scriptInfo); })
                };
            };
            Session.prototype.getNavigationTree = function (args, simplifiedResult) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var tree = languageService.getNavigationTree(file);
                return !tree
                    ? undefined
                    : simplifiedResult
                        ? this.toLocationNavigationTree(tree, this.projectService.getScriptInfoForNormalizedPath(file))
                        : tree;
            };
            Session.prototype.getNavigateToItems = function (args, simplifiedResult) {
                var full = this.getFullNavigateToItems(args);
                return !simplifiedResult ?
                    ts.flatMap(full, function (_a) {
                        var navigateToItems = _a.navigateToItems;
                        return navigateToItems;
                    }) :
                    ts.flatMap(full, function (_a) {
                        var project = _a.project, navigateToItems = _a.navigateToItems;
                        return navigateToItems.map(function (navItem) {
                            var scriptInfo = project.getScriptInfo(navItem.fileName);
                            var bakedItem = {
                                name: navItem.name,
                                kind: navItem.kind,
                                kindModifiers: navItem.kindModifiers,
                                isCaseSensitive: navItem.isCaseSensitive,
                                matchKind: navItem.matchKind,
                                file: navItem.fileName,
                                start: scriptInfo.positionToLineOffset(navItem.textSpan.start),
                                end: scriptInfo.positionToLineOffset(ts.textSpanEnd(navItem.textSpan))
                            };
                            if (navItem.kindModifiers && (navItem.kindModifiers !== "")) {
                                bakedItem.kindModifiers = navItem.kindModifiers;
                            }
                            if (navItem.containerName && (navItem.containerName.length > 0)) {
                                bakedItem.containerName = navItem.containerName;
                            }
                            if (navItem.containerKind && (navItem.containerKind.length > 0)) {
                                bakedItem.containerKind = navItem.containerKind;
                            }
                            return bakedItem;
                        });
                    });
            };
            Session.prototype.getFullNavigateToItems = function (args) {
                var currentFileOnly = args.currentFileOnly, searchValue = args.searchValue, maxResultCount = args.maxResultCount, projectFileName = args.projectFileName;
                if (currentFileOnly) {
                    ts.Debug.assertIsDefined(args.file);
                    var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                    return [{ project: project, navigateToItems: project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, file) }];
                }
                var outputs = [];
                // This is effectively a hashset with `name` as the custom hash and `navigateToItemIsEqualTo` as the custom equals.
                // `name` is a very cheap hash function, but we could incorporate other properties to reduce collisions.
                var seenItems = new ts.Map(); // name to items with that name
                if (!args.file && !projectFileName) {
                    // VS Code's `Go to symbol in workspaces` sends request like this
                    // TODO (https://github.com/microsoft/TypeScript/issues/47839)
                    // This appears to have been intended to search all projects but, in practice, it seems to only search
                    // those that are downstream from already-loaded projects.
                    // Filtering by !isSourceOfProjectReferenceRedirect is new, but seems appropriate and consistent with
                    // the case below.
                    this.projectService.loadAncestorProjectTree();
                    this.projectService.forEachEnabledProject(function (project) { return addItemsForProject(project); });
                }
                else {
                    // VS's `Go to symbol` sends requests with just a project and doesn't want cascading since it will
                    // send a separate request for each project of interest
                    // TODO (https://github.com/microsoft/TypeScript/issues/47839)
                    // This doesn't really make sense unless it's a single project matching `projectFileName`
                    var projects = this.getProjects(args);
                    forEachProjectInProjects(projects, /*path*/ undefined, function (project) { return addItemsForProject(project); });
                }
                return outputs;
                // Mutates `outputs`
                function addItemsForProject(project) {
                    var projectItems = project.getLanguageService().getNavigateToItems(searchValue, maxResultCount, /*filename*/ undefined, /*excludeDts*/ project.isNonTsProject());
                    var unseenItems = ts.filter(projectItems, function (item) { return tryAddSeenItem(item) && !getMappedLocation(documentSpanLocation(item), project); });
                    if (unseenItems.length) {
                        outputs.push({ project: project, navigateToItems: unseenItems });
                    }
                }
                // Returns true if the item had not been seen before
                // Mutates `seenItems`
                function tryAddSeenItem(item) {
                    var name = item.name;
                    if (!seenItems.has(name)) {
                        seenItems.set(name, [item]);
                        return true;
                    }
                    var seen = seenItems.get(name);
                    for (var _i = 0, seen_1 = seen; _i < seen_1.length; _i++) {
                        var seenItem = seen_1[_i];
                        if (navigateToItemIsEqualTo(seenItem, item)) {
                            return false;
                        }
                    }
                    seen.push(item);
                    return true;
                }
                function navigateToItemIsEqualTo(a, b) {
                    if (a === b) {
                        return true;
                    }
                    if (!a || !b) {
                        return false;
                    }
                    return a.containerKind === b.containerKind &&
                        a.containerName === b.containerName &&
                        a.fileName === b.fileName &&
                        a.isCaseSensitive === b.isCaseSensitive &&
                        a.kind === b.kind &&
                        a.kindModifiers === b.kindModifiers &&
                        a.matchKind === b.matchKind &&
                        a.name === b.name &&
                        a.textSpan.start === b.textSpan.start &&
                        a.textSpan.length === b.textSpan.length;
                }
            };
            Session.prototype.getSupportedCodeFixes = function () {
                return ts.getSupportedCodeFixes();
            };
            Session.prototype.isLocation = function (locationOrSpan) {
                return locationOrSpan.line !== undefined;
            };
            Session.prototype.extractPositionOrRange = function (args, scriptInfo) {
                var position;
                var textRange;
                if (this.isLocation(args)) {
                    position = getPosition(args);
                }
                else {
                    textRange = this.getRange(args, scriptInfo);
                }
                return ts.Debug.checkDefined(position === undefined ? textRange : position);
                function getPosition(loc) {
                    return loc.position !== undefined ? loc.position : scriptInfo.lineOffsetToPosition(loc.line, loc.offset);
                }
            };
            Session.prototype.getRange = function (args, scriptInfo) {
                var _a = this.getStartAndEndPosition(args, scriptInfo), startPosition = _a.startPosition, endPosition = _a.endPosition;
                return { pos: startPosition, end: endPosition };
            };
            Session.prototype.getApplicableRefactors = function (args) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = project.getScriptInfoForNormalizedPath(file);
                return project.getLanguageService().getApplicableRefactors(file, this.extractPositionOrRange(args, scriptInfo), this.getPreferences(file), args.triggerReason, args.kind);
            };
            Session.prototype.getEditsForRefactor = function (args, simplifiedResult) {
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = project.getScriptInfoForNormalizedPath(file);
                var result = project.getLanguageService().getEditsForRefactor(file, this.getFormatOptions(file), this.extractPositionOrRange(args, scriptInfo), args.refactor, args.action, this.getPreferences(file));
                if (result === undefined) {
                    return {
                        edits: []
                    };
                }
                if (simplifiedResult) {
                    var renameFilename = result.renameFilename, renameLocation = result.renameLocation, edits = result.edits;
                    var mappedRenameLocation = void 0;
                    if (renameFilename !== undefined && renameLocation !== undefined) {
                        var renameScriptInfo = project.getScriptInfoForNormalizedPath(server.toNormalizedPath(renameFilename));
                        mappedRenameLocation = getLocationInNewDocument(ts.getSnapshotText(renameScriptInfo.getSnapshot()), renameFilename, renameLocation, edits);
                    }
                    return { renameLocation: mappedRenameLocation, renameFilename: renameFilename, edits: this.mapTextChangesToCodeEdits(edits) };
                }
                else {
                    return result;
                }
            };
            Session.prototype.organizeImports = function (args, simplifiedResult) {
                ts.Debug.assert(args.scope.type === "file");
                var _a = this.getFileAndProject(args.scope.args), file = _a.file, project = _a.project;
                var changes = project.getLanguageService().organizeImports({
                    fileName: file,
                    skipDestructiveCodeActions: args.skipDestructiveCodeActions,
                    type: "file",
                }, this.getFormatOptions(file), this.getPreferences(file));
                if (simplifiedResult) {
                    return this.mapTextChangesToCodeEdits(changes);
                }
                else {
                    return changes;
                }
            };
            Session.prototype.getEditsForFileRename = function (args, simplifiedResult) {
                var _this = this;
                var oldPath = server.toNormalizedPath(args.oldFilePath);
                var newPath = server.toNormalizedPath(args.newFilePath);
                var formatOptions = this.getHostFormatOptions();
                var preferences = this.getHostPreferences();
                var seenFiles = new ts.Set();
                var textChanges = [];
                // TODO (https://github.com/microsoft/TypeScript/issues/47839)
                // This appears to have been intended to search all projects but, in practice, it seems to only search
                // those that are downstream from already-loaded projects.
                this.projectService.loadAncestorProjectTree();
                this.projectService.forEachEnabledProject(function (project) {
                    var projectTextChanges = project.getLanguageService().getEditsForFileRename(oldPath, newPath, formatOptions, preferences);
                    var projectFiles = [];
                    for (var _i = 0, projectTextChanges_1 = projectTextChanges; _i < projectTextChanges_1.length; _i++) {
                        var textChange = projectTextChanges_1[_i];
                        if (!seenFiles.has(textChange.fileName)) {
                            textChanges.push(textChange);
                            projectFiles.push(textChange.fileName);
                        }
                    }
                    for (var _a = 0, projectFiles_1 = projectFiles; _a < projectFiles_1.length; _a++) {
                        var file = projectFiles_1[_a];
                        seenFiles.add(file);
                    }
                });
                return simplifiedResult ? textChanges.map(function (c) { return _this.mapTextChangeToCodeEdit(c); }) : textChanges;
            };
            Session.prototype.getCodeFixes = function (args, simplifiedResult) {
                var _this = this;
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = project.getScriptInfoForNormalizedPath(file);
                var _b = this.getStartAndEndPosition(args, scriptInfo), startPosition = _b.startPosition, endPosition = _b.endPosition;
                var codeActions;
                try {
                    codeActions = project.getLanguageService().getCodeFixesAtPosition(file, startPosition, endPosition, args.errorCodes, this.getFormatOptions(file), this.getPreferences(file));
                }
                catch (e) {
                    var ls = project.getLanguageService();
                    var existingDiagCodes_1 = __spreadArray(__spreadArray(__spreadArray([], ls.getSyntacticDiagnostics(file), true), ls.getSemanticDiagnostics(file), true), ls.getSuggestionDiagnostics(file), true).map(function (d) {
                        return ts.decodedTextSpanIntersectsWith(startPosition, endPosition - startPosition, d.start, d.length)
                            && d.code;
                    });
                    var badCode = args.errorCodes.find(function (c) { return !existingDiagCodes_1.includes(c); });
                    if (badCode !== undefined) {
                        e.message = "BADCLIENT: Bad error code, ".concat(badCode, " not found in range ").concat(startPosition, "..").concat(endPosition, " (found: ").concat(existingDiagCodes_1.join(", "), "); could have caused this error:\n").concat(e.message);
                    }
                    throw e;
                }
                return simplifiedResult ? codeActions.map(function (codeAction) { return _this.mapCodeFixAction(codeAction); }) : codeActions;
            };
            Session.prototype.getCombinedCodeFix = function (_a, simplifiedResult) {
                var scope = _a.scope, fixId = _a.fixId;
                ts.Debug.assert(scope.type === "file");
                var _b = this.getFileAndProject(scope.args), file = _b.file, project = _b.project;
                var res = project.getLanguageService().getCombinedCodeFix({ type: "file", fileName: file }, fixId, this.getFormatOptions(file), this.getPreferences(file));
                if (simplifiedResult) {
                    return { changes: this.mapTextChangesToCodeEdits(res.changes), commands: res.commands };
                }
                else {
                    return res;
                }
            };
            Session.prototype.applyCodeActionCommand = function (args) {
                var commands = args.command; // They should be sending back the command we sent them.
                for (var _i = 0, _a = ts.toArray(commands); _i < _a.length; _i++) {
                    var command = _a[_i];
                    var _b = this.getFileAndProject(command), file = _b.file, project = _b.project;
                    project.getLanguageService().applyCodeActionCommand(command, this.getFormatOptions(file)).then(function (_result) { }, function (_error) { });
                }
                return {};
            };
            Session.prototype.getStartAndEndPosition = function (args, scriptInfo) {
                var startPosition, endPosition;
                if (args.startPosition !== undefined) {
                    startPosition = args.startPosition;
                }
                else {
                    startPosition = scriptInfo.lineOffsetToPosition(args.startLine, args.startOffset);
                    // save the result so we don't always recompute
                    args.startPosition = startPosition;
                }
                if (args.endPosition !== undefined) {
                    endPosition = args.endPosition;
                }
                else {
                    endPosition = scriptInfo.lineOffsetToPosition(args.endLine, args.endOffset);
                    args.endPosition = endPosition;
                }
                return { startPosition: startPosition, endPosition: endPosition };
            };
            Session.prototype.mapCodeAction = function (_a) {
                var description = _a.description, changes = _a.changes, commands = _a.commands;
                return { description: description, changes: this.mapTextChangesToCodeEdits(changes), commands: commands };
            };
            Session.prototype.mapCodeFixAction = function (_a) {
                var fixName = _a.fixName, description = _a.description, changes = _a.changes, commands = _a.commands, fixId = _a.fixId, fixAllDescription = _a.fixAllDescription;
                return { fixName: fixName, description: description, changes: this.mapTextChangesToCodeEdits(changes), commands: commands, fixId: fixId, fixAllDescription: fixAllDescription };
            };
            Session.prototype.mapTextChangesToCodeEdits = function (textChanges) {
                var _this = this;
                return textChanges.map(function (change) { return _this.mapTextChangeToCodeEdit(change); });
            };
            Session.prototype.mapTextChangeToCodeEdit = function (textChanges) {
                var scriptInfo = this.projectService.getScriptInfoOrConfig(textChanges.fileName);
                if (!!textChanges.isNewFile === !!scriptInfo) {
                    if (!scriptInfo) { // and !isNewFile
                        this.projectService.logErrorForScriptInfoNotFound(textChanges.fileName);
                    }
                    ts.Debug.fail("Expected isNewFile for (only) new files. " + JSON.stringify({ isNewFile: !!textChanges.isNewFile, hasScriptInfo: !!scriptInfo }));
                }
                return scriptInfo
                    ? { fileName: textChanges.fileName, textChanges: textChanges.textChanges.map(function (textChange) { return convertTextChangeToCodeEdit(textChange, scriptInfo); }) }
                    : convertNewFileTextChangeToCodeEdit(textChanges);
            };
            Session.prototype.convertTextChangeToCodeEdit = function (change, scriptInfo) {
                return {
                    start: scriptInfo.positionToLineOffset(change.span.start),
                    end: scriptInfo.positionToLineOffset(change.span.start + change.span.length),
                    newText: change.newText ? change.newText : ""
                };
            };
            Session.prototype.getBraceMatching = function (args, simplifiedResult) {
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var position = this.getPosition(args, scriptInfo);
                var spans = languageService.getBraceMatchingAtPosition(file, position);
                return !spans
                    ? undefined
                    : simplifiedResult
                        ? spans.map(function (span) { return toProtocolTextSpan(span, scriptInfo); })
                        : spans;
            };
            Session.prototype.getDiagnosticsForProject = function (next, delay, fileName) {
                if (this.suppressDiagnosticEvents) {
                    return;
                }
                var _a = this.getProjectInfoWorker(fileName, /*projectFileName*/ undefined, /*needFileNameList*/ true, /*excludeConfigFiles*/ true), fileNames = _a.fileNames, languageServiceDisabled = _a.languageServiceDisabled;
                if (languageServiceDisabled) {
                    return;
                }
                // No need to analyze lib.d.ts
                var fileNamesInProject = fileNames.filter(function (value) { return !ts.stringContains(value, "lib.d.ts"); }); // TODO: GH#18217
                if (fileNamesInProject.length === 0) {
                    return;
                }
                // Sort the file name list to make the recently touched files come first
                var highPriorityFiles = [];
                var mediumPriorityFiles = [];
                var lowPriorityFiles = [];
                var veryLowPriorityFiles = [];
                var normalizedFileName = server.toNormalizedPath(fileName);
                var project = this.projectService.ensureDefaultProjectForFile(normalizedFileName);
                for (var _i = 0, fileNamesInProject_1 = fileNamesInProject; _i < fileNamesInProject_1.length; _i++) {
                    var fileNameInProject = fileNamesInProject_1[_i];
                    if (this.getCanonicalFileName(fileNameInProject) === this.getCanonicalFileName(fileName)) {
                        highPriorityFiles.push(fileNameInProject);
                    }
                    else {
                        var info = this.projectService.getScriptInfo(fileNameInProject); // TODO: GH#18217
                        if (!info.isScriptOpen()) {
                            if (ts.isDeclarationFileName(fileNameInProject)) {
                                veryLowPriorityFiles.push(fileNameInProject);
                            }
                            else {
                                lowPriorityFiles.push(fileNameInProject);
                            }
                        }
                        else {
                            mediumPriorityFiles.push(fileNameInProject);
                        }
                    }
                }
                var sortedFiles = __spreadArray(__spreadArray(__spreadArray(__spreadArray([], highPriorityFiles, true), mediumPriorityFiles, true), lowPriorityFiles, true), veryLowPriorityFiles, true);
                var checkList = sortedFiles.map(function (fileName) { return ({ fileName: fileName, project: project }); });
                // Project level error analysis runs on background files too, therefore
                // doesn't require the file to be opened
                this.updateErrorCheck(next, checkList, delay, /*requireOpen*/ false);
            };
            Session.prototype.configurePlugin = function (args) {
                this.projectService.configurePlugin(args);
            };
            Session.prototype.getSmartSelectionRange = function (args, simplifiedResult) {
                var _this = this;
                var locations = args.locations;
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var scriptInfo = ts.Debug.checkDefined(this.projectService.getScriptInfo(file));
                return ts.map(locations, function (location) {
                    var pos = _this.getPosition(location, scriptInfo);
                    var selectionRange = languageService.getSmartSelectionRange(file, pos);
                    return simplifiedResult ? _this.mapSelectionRange(selectionRange, scriptInfo) : selectionRange;
                });
            };
            Session.prototype.toggleLineComment = function (args, simplifiedResult) {
                var _this = this;
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var scriptInfo = this.projectService.getScriptInfo(file);
                var textRange = this.getRange(args, scriptInfo);
                var textChanges = languageService.toggleLineComment(file, textRange);
                if (simplifiedResult) {
                    var scriptInfo_2 = this.projectService.getScriptInfoForNormalizedPath(file);
                    return textChanges.map(function (textChange) { return _this.convertTextChangeToCodeEdit(textChange, scriptInfo_2); });
                }
                return textChanges;
            };
            Session.prototype.toggleMultilineComment = function (args, simplifiedResult) {
                var _this = this;
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var textRange = this.getRange(args, scriptInfo);
                var textChanges = languageService.toggleMultilineComment(file, textRange);
                if (simplifiedResult) {
                    var scriptInfo_3 = this.projectService.getScriptInfoForNormalizedPath(file);
                    return textChanges.map(function (textChange) { return _this.convertTextChangeToCodeEdit(textChange, scriptInfo_3); });
                }
                return textChanges;
            };
            Session.prototype.commentSelection = function (args, simplifiedResult) {
                var _this = this;
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var textRange = this.getRange(args, scriptInfo);
                var textChanges = languageService.commentSelection(file, textRange);
                if (simplifiedResult) {
                    var scriptInfo_4 = this.projectService.getScriptInfoForNormalizedPath(file);
                    return textChanges.map(function (textChange) { return _this.convertTextChangeToCodeEdit(textChange, scriptInfo_4); });
                }
                return textChanges;
            };
            Session.prototype.uncommentSelection = function (args, simplifiedResult) {
                var _this = this;
                var _a = this.getFileAndLanguageServiceForSyntacticOperation(args), file = _a.file, languageService = _a.languageService;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                var textRange = this.getRange(args, scriptInfo);
                var textChanges = languageService.uncommentSelection(file, textRange);
                if (simplifiedResult) {
                    var scriptInfo_5 = this.projectService.getScriptInfoForNormalizedPath(file);
                    return textChanges.map(function (textChange) { return _this.convertTextChangeToCodeEdit(textChange, scriptInfo_5); });
                }
                return textChanges;
            };
            Session.prototype.mapSelectionRange = function (selectionRange, scriptInfo) {
                var result = {
                    textSpan: toProtocolTextSpan(selectionRange.textSpan, scriptInfo),
                };
                if (selectionRange.parent) {
                    result.parent = this.mapSelectionRange(selectionRange.parent, scriptInfo);
                }
                return result;
            };
            Session.prototype.getScriptInfoFromProjectService = function (file) {
                var normalizedFile = server.toNormalizedPath(file);
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(normalizedFile);
                if (!scriptInfo) {
                    this.projectService.logErrorForScriptInfoNotFound(normalizedFile);
                    return server.Errors.ThrowNoProject();
                }
                return scriptInfo;
            };
            Session.prototype.toProtocolCallHierarchyItem = function (item) {
                var scriptInfo = this.getScriptInfoFromProjectService(item.file);
                return {
                    name: item.name,
                    kind: item.kind,
                    kindModifiers: item.kindModifiers,
                    file: item.file,
                    containerName: item.containerName,
                    span: toProtocolTextSpan(item.span, scriptInfo),
                    selectionSpan: toProtocolTextSpan(item.selectionSpan, scriptInfo)
                };
            };
            Session.prototype.toProtocolCallHierarchyIncomingCall = function (incomingCall) {
                var scriptInfo = this.getScriptInfoFromProjectService(incomingCall.from.file);
                return {
                    from: this.toProtocolCallHierarchyItem(incomingCall.from),
                    fromSpans: incomingCall.fromSpans.map(function (fromSpan) { return toProtocolTextSpan(fromSpan, scriptInfo); })
                };
            };
            Session.prototype.toProtocolCallHierarchyOutgoingCall = function (outgoingCall, scriptInfo) {
                return {
                    to: this.toProtocolCallHierarchyItem(outgoingCall.to),
                    fromSpans: outgoingCall.fromSpans.map(function (fromSpan) { return toProtocolTextSpan(fromSpan, scriptInfo); })
                };
            };
            Session.prototype.prepareCallHierarchy = function (args) {
                var _this = this;
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = this.projectService.getScriptInfoForNormalizedPath(file);
                if (scriptInfo) {
                    var position = this.getPosition(args, scriptInfo);
                    var result = project.getLanguageService().prepareCallHierarchy(file, position);
                    return result && ts.mapOneOrMany(result, function (item) { return _this.toProtocolCallHierarchyItem(item); });
                }
                return undefined;
            };
            Session.prototype.provideCallHierarchyIncomingCalls = function (args) {
                var _this = this;
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = this.getScriptInfoFromProjectService(file);
                var incomingCalls = project.getLanguageService().provideCallHierarchyIncomingCalls(file, this.getPosition(args, scriptInfo));
                return incomingCalls.map(function (call) { return _this.toProtocolCallHierarchyIncomingCall(call); });
            };
            Session.prototype.provideCallHierarchyOutgoingCalls = function (args) {
                var _this = this;
                var _a = this.getFileAndProject(args), file = _a.file, project = _a.project;
                var scriptInfo = this.getScriptInfoFromProjectService(file);
                var outgoingCalls = project.getLanguageService().provideCallHierarchyOutgoingCalls(file, this.getPosition(args, scriptInfo));
                return outgoingCalls.map(function (call) { return _this.toProtocolCallHierarchyOutgoingCall(call, scriptInfo); });
            };
            Session.prototype.getCanonicalFileName = function (fileName) {
                var name = this.host.useCaseSensitiveFileNames ? fileName : ts.toFileNameLowerCase(fileName);
                return ts.normalizePath(name);
            };
            Session.prototype.exit = function () { };
            Session.prototype.notRequired = function () {
                return { responseRequired: false };
            };
            Session.prototype.requiredResponse = function (response) {
                return { response: response, responseRequired: true };
            };
            Session.prototype.addProtocolHandler = function (command, handler) {
                if (this.handlers.has(command)) {
                    throw new Error("Protocol handler already exists for command \"".concat(command, "\""));
                }
                this.handlers.set(command, handler);
            };
            Session.prototype.setCurrentRequest = function (requestId) {
                ts.Debug.assert(this.currentRequestId === undefined);
                this.currentRequestId = requestId;
                this.cancellationToken.setRequest(requestId);
            };
            Session.prototype.resetCurrentRequest = function (requestId) {
                ts.Debug.assert(this.currentRequestId === requestId);
                this.currentRequestId = undefined; // TODO: GH#18217
                this.cancellationToken.resetRequest(requestId);
            };
            Session.prototype.executeWithRequestId = function (requestId, f) {
                try {
                    this.setCurrentRequest(requestId);
                    return f();
                }
                finally {
                    this.resetCurrentRequest(requestId);
                }
            };
            Session.prototype.executeCommand = function (request) {
                var handler = this.handlers.get(request.command);
                if (handler) {
                    return this.executeWithRequestId(request.seq, function () { return handler(request); });
                }
                else {
                    this.logger.msg("Unrecognized JSON command:".concat(server.stringifyIndented(request)), server.Msg.Err);
                    this.doOutput(/*info*/ undefined, server.CommandNames.Unknown, request.seq, /*success*/ false, "Unrecognized JSON command: ".concat(request.command));
                    return { responseRequired: false };
                }
            };
            Session.prototype.onMessage = function (message) {
                this.gcTimer.scheduleCollect();
                this.performanceData = undefined;
                var start;
                if (this.logger.hasLevel(server.LogLevel.requestTime)) {
                    start = this.hrtime();
                    if (this.logger.hasLevel(server.LogLevel.verbose)) {
                        this.logger.info("request:".concat(server.indent(this.toStringMessage(message))));
                    }
                }
                var request;
                var relevantFile;
                try {
                    request = this.parseMessage(message);
                    relevantFile = request.arguments && request.arguments.file ? request.arguments : undefined;
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "request", { seq: request.seq, command: request.command });
                    ts.perfLogger.logStartCommand("" + request.command, this.toStringMessage(message).substring(0, 100));
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.push("session" /* tracing.Phase.Session */, "executeCommand", { seq: request.seq, command: request.command }, /*separateBeginAndEnd*/ true);
                    var _a = this.executeCommand(request), response = _a.response, responseRequired = _a.responseRequired;
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.pop();
                    if (this.logger.hasLevel(server.LogLevel.requestTime)) {
                        var elapsedTime = hrTimeToMilliseconds(this.hrtime(start)).toFixed(4);
                        if (responseRequired) {
                            this.logger.perftrc("".concat(request.seq, "::").concat(request.command, ": elapsed time (in milliseconds) ").concat(elapsedTime));
                        }
                        else {
                            this.logger.perftrc("".concat(request.seq, "::").concat(request.command, ": async elapsed time (in milliseconds) ").concat(elapsedTime));
                        }
                    }
                    // Note: Log before writing the response, else the editor can complete its activity before the server does
                    ts.perfLogger.logStopCommand("" + request.command, "Success");
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "response", { seq: request.seq, command: request.command, success: !!response });
                    if (response) {
                        this.doOutput(response, request.command, request.seq, /*success*/ true);
                    }
                    else if (responseRequired) {
                        this.doOutput(/*info*/ undefined, request.command, request.seq, /*success*/ false, "No content available.");
                    }
                }
                catch (err) {
                    // Cancellation or an error may have left incomplete events on the tracing stack.
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.popAll();
                    if (err instanceof ts.OperationCanceledException) {
                        // Handle cancellation exceptions
                        ts.perfLogger.logStopCommand("" + (request && request.command), "Canceled: " + err);
                        ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "commandCanceled", { seq: request === null || request === void 0 ? void 0 : request.seq, command: request === null || request === void 0 ? void 0 : request.command });
                        this.doOutput({ canceled: true }, request.command, request.seq, /*success*/ true);
                        return;
                    }
                    this.logErrorWorker(err, this.toStringMessage(message), relevantFile);
                    ts.perfLogger.logStopCommand("" + (request && request.command), "Error: " + err);
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.instant("session" /* tracing.Phase.Session */, "commandError", { seq: request === null || request === void 0 ? void 0 : request.seq, command: request === null || request === void 0 ? void 0 : request.command, message: err.message });
                    this.doOutput(
                    /*info*/ undefined, request ? request.command : server.CommandNames.Unknown, request ? request.seq : 0, 
                    /*success*/ false, "Error processing request. " + err.message + "\n" + err.stack);
                }
            };
            Session.prototype.parseMessage = function (message) {
                return JSON.parse(message);
            };
            Session.prototype.toStringMessage = function (message) {
                return message;
            };
            Session.prototype.getFormatOptions = function (file) {
                return this.projectService.getFormatCodeOptions(file);
            };
            Session.prototype.getPreferences = function (file) {
                return this.projectService.getPreferences(file);
            };
            Session.prototype.getHostFormatOptions = function () {
                return this.projectService.getHostFormatCodeOptions();
            };
            Session.prototype.getHostPreferences = function () {
                return this.projectService.getHostPreferences();
            };
            return Session;
        }());
        server.Session = Session;
        function toProtocolTextSpan(textSpan, scriptInfo) {
            return {
                start: scriptInfo.positionToLineOffset(textSpan.start),
                end: scriptInfo.positionToLineOffset(ts.textSpanEnd(textSpan))
            };
        }
        function toProtocolTextSpanWithContext(span, contextSpan, scriptInfo) {
            var textSpan = toProtocolTextSpan(span, scriptInfo);
            var contextTextSpan = contextSpan && toProtocolTextSpan(contextSpan, scriptInfo);
            return contextTextSpan ? __assign(__assign({}, textSpan), { contextStart: contextTextSpan.start, contextEnd: contextTextSpan.end }) :
                textSpan;
        }
        function convertTextChangeToCodeEdit(change, scriptInfo) {
            return { start: positionToLineOffset(scriptInfo, change.span.start), end: positionToLineOffset(scriptInfo, ts.textSpanEnd(change.span)), newText: change.newText };
        }
        function positionToLineOffset(info, position) {
            return server.isConfigFile(info) ? locationFromLineAndCharacter(info.getLineAndCharacterOfPosition(position)) : info.positionToLineOffset(position);
        }
        function locationFromLineAndCharacter(lc) {
            return { line: lc.line + 1, offset: lc.character + 1 };
        }
        function convertNewFileTextChangeToCodeEdit(textChanges) {
            ts.Debug.assert(textChanges.textChanges.length === 1);
            var change = ts.first(textChanges.textChanges);
            ts.Debug.assert(change.span.start === 0 && change.span.length === 0);
            return { fileName: textChanges.fileName, textChanges: [{ start: { line: 0, offset: 0 }, end: { line: 0, offset: 0 }, newText: change.newText }] };
        }
        /* @internal */ // Exported only for tests
        function getLocationInNewDocument(oldText, renameFilename, renameLocation, edits) {
            var newText = applyEdits(oldText, renameFilename, edits);
            var _a = ts.computeLineAndCharacterOfPosition(ts.computeLineStarts(newText), renameLocation), line = _a.line, character = _a.character;
            return { line: line + 1, offset: character + 1 };
        }
        server.getLocationInNewDocument = getLocationInNewDocument;
        function applyEdits(text, textFilename, edits) {
            for (var _i = 0, edits_1 = edits; _i < edits_1.length; _i++) {
                var _a = edits_1[_i], fileName = _a.fileName, textChanges_1 = _a.textChanges;
                if (fileName !== textFilename) {
                    continue;
                }
                for (var i = textChanges_1.length - 1; i >= 0; i--) {
                    var _b = textChanges_1[i], newText = _b.newText, _c = _b.span, start = _c.start, length_1 = _c.length;
                    text = text.slice(0, start) + newText + text.slice(start + length_1);
                }
            }
            return text;
        }
        function referenceEntryToReferencesResponseItem(projectService, _a) {
            var fileName = _a.fileName, textSpan = _a.textSpan, contextSpan = _a.contextSpan, isWriteAccess = _a.isWriteAccess, isDefinition = _a.isDefinition;
            var scriptInfo = ts.Debug.checkDefined(projectService.getScriptInfo(fileName));
            var span = toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo);
            var lineSpan = scriptInfo.lineToTextSpan(span.start.line - 1);
            var lineText = scriptInfo.getSnapshot().getText(lineSpan.start, ts.textSpanEnd(lineSpan)).replace(/\r|\n/g, "");
            return __assign(__assign({ file: fileName }, span), { lineText: lineText, isWriteAccess: isWriteAccess, isDefinition: isDefinition });
        }
        function isCompletionEntryData(data) {
            return data === undefined || data && typeof data === "object"
                && typeof data.exportName === "string"
                && (data.fileName === undefined || typeof data.fileName === "string")
                && (data.ambientModuleName === undefined || typeof data.ambientModuleName === "string"
                    && (data.isPackageJsonImport === undefined || typeof data.isPackageJsonImport === "boolean"));
        }
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/*@internal*/
var ts;
(function (ts) {
    var server;
    (function (server) {
        var lineCollectionCapacity = 4;
        var CharRangeSection;
        (function (CharRangeSection) {
            CharRangeSection[CharRangeSection["PreStart"] = 0] = "PreStart";
            CharRangeSection[CharRangeSection["Start"] = 1] = "Start";
            CharRangeSection[CharRangeSection["Entire"] = 2] = "Entire";
            CharRangeSection[CharRangeSection["Mid"] = 3] = "Mid";
            CharRangeSection[CharRangeSection["End"] = 4] = "End";
            CharRangeSection[CharRangeSection["PostEnd"] = 5] = "PostEnd";
        })(CharRangeSection || (CharRangeSection = {}));
        var EditWalker = /** @class */ (function () {
            function EditWalker() {
                this.goSubtree = true;
                this.lineIndex = new LineIndex();
                this.endBranch = [];
                this.state = 2 /* CharRangeSection.Entire */;
                this.initialText = "";
                this.trailingText = "";
                this.lineIndex.root = new LineNode();
                this.startPath = [this.lineIndex.root];
                this.stack = [this.lineIndex.root];
            }
            Object.defineProperty(EditWalker.prototype, "done", {
                get: function () { return false; },
                enumerable: false,
                configurable: true
            });
            EditWalker.prototype.insertLines = function (insertedText, suppressTrailingText) {
                if (suppressTrailingText) {
                    this.trailingText = "";
                }
                if (insertedText) {
                    insertedText = this.initialText + insertedText + this.trailingText;
                }
                else {
                    insertedText = this.initialText + this.trailingText;
                }
                var lm = LineIndex.linesFromText(insertedText);
                var lines = lm.lines;
                if (lines.length > 1 && lines[lines.length - 1] === "") {
                    lines.pop();
                }
                var branchParent;
                var lastZeroCount;
                for (var k = this.endBranch.length - 1; k >= 0; k--) {
                    this.endBranch[k].updateCounts();
                    if (this.endBranch[k].charCount() === 0) {
                        lastZeroCount = this.endBranch[k];
                        if (k > 0) {
                            branchParent = this.endBranch[k - 1];
                        }
                        else {
                            branchParent = this.branchNode;
                        }
                    }
                }
                if (lastZeroCount) {
                    branchParent.remove(lastZeroCount);
                }
                // path at least length two (root and leaf)
                var leafNode = this.startPath[this.startPath.length - 1];
                if (lines.length > 0) {
                    leafNode.text = lines[0];
                    if (lines.length > 1) {
                        var insertedNodes = new Array(lines.length - 1);
                        var startNode = leafNode;
                        for (var i = 1; i < lines.length; i++) {
                            insertedNodes[i - 1] = new LineLeaf(lines[i]);
                        }
                        var pathIndex = this.startPath.length - 2;
                        while (pathIndex >= 0) {
                            var insertionNode = this.startPath[pathIndex];
                            insertedNodes = insertionNode.insertAt(startNode, insertedNodes);
                            pathIndex--;
                            startNode = insertionNode;
                        }
                        var insertedNodesLen = insertedNodes.length;
                        while (insertedNodesLen > 0) {
                            var newRoot = new LineNode();
                            newRoot.add(this.lineIndex.root);
                            insertedNodes = newRoot.insertAt(this.lineIndex.root, insertedNodes);
                            insertedNodesLen = insertedNodes.length;
                            this.lineIndex.root = newRoot;
                        }
                        this.lineIndex.root.updateCounts();
                    }
                    else {
                        for (var j = this.startPath.length - 2; j >= 0; j--) {
                            this.startPath[j].updateCounts();
                        }
                    }
                }
                else {
                    var insertionNode = this.startPath[this.startPath.length - 2];
                    // no content for leaf node, so delete it
                    insertionNode.remove(leafNode);
                    for (var j = this.startPath.length - 2; j >= 0; j--) {
                        this.startPath[j].updateCounts();
                    }
                }
                return this.lineIndex;
            };
            EditWalker.prototype.post = function (_relativeStart, _relativeLength, lineCollection) {
                // have visited the path for start of range, now looking for end
                // if range is on single line, we will never make this state transition
                if (lineCollection === this.lineCollectionAtBranch) {
                    this.state = 4 /* CharRangeSection.End */;
                }
                // always pop stack because post only called when child has been visited
                this.stack.pop();
            };
            EditWalker.prototype.pre = function (_relativeStart, _relativeLength, lineCollection, _parent, nodeType) {
                // currentNode corresponds to parent, but in the new tree
                var currentNode = this.stack[this.stack.length - 1];
                if ((this.state === 2 /* CharRangeSection.Entire */) && (nodeType === 1 /* CharRangeSection.Start */)) {
                    // if range is on single line, we will never make this state transition
                    this.state = 1 /* CharRangeSection.Start */;
                    this.branchNode = currentNode;
                    this.lineCollectionAtBranch = lineCollection;
                }
                var child;
                function fresh(node) {
                    if (node.isLeaf()) {
                        return new LineLeaf("");
                    }
                    else
                        return new LineNode();
                }
                switch (nodeType) {
                    case 0 /* CharRangeSection.PreStart */:
                        this.goSubtree = false;
                        if (this.state !== 4 /* CharRangeSection.End */) {
                            currentNode.add(lineCollection);
                        }
                        break;
                    case 1 /* CharRangeSection.Start */:
                        if (this.state === 4 /* CharRangeSection.End */) {
                            this.goSubtree = false;
                        }
                        else {
                            child = fresh(lineCollection);
                            currentNode.add(child);
                            this.startPath.push(child);
                        }
                        break;
                    case 2 /* CharRangeSection.Entire */:
                        if (this.state !== 4 /* CharRangeSection.End */) {
                            child = fresh(lineCollection);
                            currentNode.add(child);
                            this.startPath.push(child);
                        }
                        else {
                            if (!lineCollection.isLeaf()) {
                                child = fresh(lineCollection);
                                currentNode.add(child);
                                this.endBranch.push(child);
                            }
                        }
                        break;
                    case 3 /* CharRangeSection.Mid */:
                        this.goSubtree = false;
                        break;
                    case 4 /* CharRangeSection.End */:
                        if (this.state !== 4 /* CharRangeSection.End */) {
                            this.goSubtree = false;
                        }
                        else {
                            if (!lineCollection.isLeaf()) {
                                child = fresh(lineCollection);
                                currentNode.add(child);
                                this.endBranch.push(child);
                            }
                        }
                        break;
                    case 5 /* CharRangeSection.PostEnd */:
                        this.goSubtree = false;
                        if (this.state !== 1 /* CharRangeSection.Start */) {
                            currentNode.add(lineCollection);
                        }
                        break;
                }
                if (this.goSubtree) {
                    this.stack.push(child);
                }
            };
            // just gather text from the leaves
            EditWalker.prototype.leaf = function (relativeStart, relativeLength, ll) {
                if (this.state === 1 /* CharRangeSection.Start */) {
                    this.initialText = ll.text.substring(0, relativeStart);
                }
                else if (this.state === 2 /* CharRangeSection.Entire */) {
                    this.initialText = ll.text.substring(0, relativeStart);
                    this.trailingText = ll.text.substring(relativeStart + relativeLength);
                }
                else {
                    // state is CharRangeSection.End
                    this.trailingText = ll.text.substring(relativeStart + relativeLength);
                }
            };
            return EditWalker;
        }());
        // text change information
        var TextChange = /** @class */ (function () {
            function TextChange(pos, deleteLen, insertedText) {
                this.pos = pos;
                this.deleteLen = deleteLen;
                this.insertedText = insertedText;
            }
            TextChange.prototype.getTextChangeRange = function () {
                return ts.createTextChangeRange(ts.createTextSpan(this.pos, this.deleteLen), this.insertedText ? this.insertedText.length : 0);
            };
            return TextChange;
        }());
        var ScriptVersionCache = /** @class */ (function () {
            function ScriptVersionCache() {
                this.changes = [];
                this.versions = new Array(ScriptVersionCache.maxVersions);
                this.minVersion = 0; // no versions earlier than min version will maintain change history
                this.currentVersion = 0;
            }
            ScriptVersionCache.prototype.versionToIndex = function (version) {
                if (version < this.minVersion || version > this.currentVersion) {
                    return undefined;
                }
                return version % ScriptVersionCache.maxVersions;
            };
            ScriptVersionCache.prototype.currentVersionToIndex = function () {
                return this.currentVersion % ScriptVersionCache.maxVersions;
            };
            // REVIEW: can optimize by coalescing simple edits
            ScriptVersionCache.prototype.edit = function (pos, deleteLen, insertedText) {
                this.changes.push(new TextChange(pos, deleteLen, insertedText));
                if (this.changes.length > ScriptVersionCache.changeNumberThreshold ||
                    deleteLen > ScriptVersionCache.changeLengthThreshold ||
                    insertedText && insertedText.length > ScriptVersionCache.changeLengthThreshold) {
                    this.getSnapshot();
                }
            };
            ScriptVersionCache.prototype.getSnapshot = function () { return this._getSnapshot(); };
            ScriptVersionCache.prototype._getSnapshot = function () {
                var snap = this.versions[this.currentVersionToIndex()];
                if (this.changes.length > 0) {
                    var snapIndex = snap.index;
                    for (var _i = 0, _a = this.changes; _i < _a.length; _i++) {
                        var change = _a[_i];
                        snapIndex = snapIndex.edit(change.pos, change.deleteLen, change.insertedText);
                    }
                    snap = new LineIndexSnapshot(this.currentVersion + 1, this, snapIndex, this.changes);
                    this.currentVersion = snap.version;
                    this.versions[this.currentVersionToIndex()] = snap;
                    this.changes = [];
                    if ((this.currentVersion - this.minVersion) >= ScriptVersionCache.maxVersions) {
                        this.minVersion = (this.currentVersion - ScriptVersionCache.maxVersions) + 1;
                    }
                }
                return snap;
            };
            ScriptVersionCache.prototype.getSnapshotVersion = function () {
                return this._getSnapshot().version;
            };
            ScriptVersionCache.prototype.getAbsolutePositionAndLineText = function (oneBasedLine) {
                return this._getSnapshot().index.lineNumberToInfo(oneBasedLine);
            };
            ScriptVersionCache.prototype.lineOffsetToPosition = function (line, column) {
                return this._getSnapshot().index.absolutePositionOfStartOfLine(line) + (column - 1);
            };
            ScriptVersionCache.prototype.positionToLineOffset = function (position) {
                return this._getSnapshot().index.positionToLineOffset(position);
            };
            ScriptVersionCache.prototype.lineToTextSpan = function (line) {
                var index = this._getSnapshot().index;
                var _a = index.lineNumberToInfo(line + 1), lineText = _a.lineText, absolutePosition = _a.absolutePosition;
                var len = lineText !== undefined ? lineText.length : index.absolutePositionOfStartOfLine(line + 2) - absolutePosition;
                return ts.createTextSpan(absolutePosition, len);
            };
            ScriptVersionCache.prototype.getTextChangesBetweenVersions = function (oldVersion, newVersion) {
                if (oldVersion < newVersion) {
                    if (oldVersion >= this.minVersion) {
                        var textChangeRanges = [];
                        for (var i = oldVersion + 1; i <= newVersion; i++) {
                            var snap = this.versions[this.versionToIndex(i)]; // TODO: GH#18217
                            for (var _i = 0, _a = snap.changesSincePreviousVersion; _i < _a.length; _i++) {
                                var textChange = _a[_i];
                                textChangeRanges.push(textChange.getTextChangeRange());
                            }
                        }
                        return ts.collapseTextChangeRangesAcrossMultipleVersions(textChangeRanges);
                    }
                    else {
                        return undefined;
                    }
                }
                else {
                    return ts.unchangedTextChangeRange;
                }
            };
            ScriptVersionCache.prototype.getLineCount = function () {
                return this._getSnapshot().index.getLineCount();
            };
            ScriptVersionCache.fromString = function (script) {
                var svc = new ScriptVersionCache();
                var snap = new LineIndexSnapshot(0, svc, new LineIndex());
                svc.versions[svc.currentVersion] = snap;
                var lm = LineIndex.linesFromText(script);
                snap.index.load(lm.lines);
                return svc;
            };
            ScriptVersionCache.changeNumberThreshold = 8;
            ScriptVersionCache.changeLengthThreshold = 256;
            ScriptVersionCache.maxVersions = 8;
            return ScriptVersionCache;
        }());
        server.ScriptVersionCache = ScriptVersionCache;
        var LineIndexSnapshot = /** @class */ (function () {
            function LineIndexSnapshot(version, cache, index, changesSincePreviousVersion) {
                if (changesSincePreviousVersion === void 0) { changesSincePreviousVersion = server.emptyArray; }
                this.version = version;
                this.cache = cache;
                this.index = index;
                this.changesSincePreviousVersion = changesSincePreviousVersion;
            }
            LineIndexSnapshot.prototype.getText = function (rangeStart, rangeEnd) {
                return this.index.getText(rangeStart, rangeEnd - rangeStart);
            };
            LineIndexSnapshot.prototype.getLength = function () {
                return this.index.getLength();
            };
            LineIndexSnapshot.prototype.getChangeRange = function (oldSnapshot) {
                if (oldSnapshot instanceof LineIndexSnapshot && this.cache === oldSnapshot.cache) {
                    if (this.version <= oldSnapshot.version) {
                        return ts.unchangedTextChangeRange;
                    }
                    else {
                        return this.cache.getTextChangesBetweenVersions(oldSnapshot.version, this.version);
                    }
                }
            };
            return LineIndexSnapshot;
        }());
        var LineIndex = /** @class */ (function () {
            function LineIndex() {
                // set this to true to check each edit for accuracy
                this.checkEdits = false;
            }
            LineIndex.prototype.absolutePositionOfStartOfLine = function (oneBasedLine) {
                return this.lineNumberToInfo(oneBasedLine).absolutePosition;
            };
            LineIndex.prototype.positionToLineOffset = function (position) {
                var _a = this.root.charOffsetToLineInfo(1, position), oneBasedLine = _a.oneBasedLine, zeroBasedColumn = _a.zeroBasedColumn;
                return { line: oneBasedLine, offset: zeroBasedColumn + 1 };
            };
            LineIndex.prototype.positionToColumnAndLineText = function (position) {
                return this.root.charOffsetToLineInfo(1, position);
            };
            LineIndex.prototype.getLineCount = function () {
                return this.root.lineCount();
            };
            LineIndex.prototype.lineNumberToInfo = function (oneBasedLine) {
                var lineCount = this.getLineCount();
                if (oneBasedLine <= lineCount) {
                    var _a = this.root.lineNumberToInfo(oneBasedLine, 0), position = _a.position, leaf = _a.leaf;
                    return { absolutePosition: position, lineText: leaf && leaf.text };
                }
                else {
                    return { absolutePosition: this.root.charCount(), lineText: undefined };
                }
            };
            LineIndex.prototype.load = function (lines) {
                if (lines.length > 0) {
                    var leaves = [];
                    for (var i = 0; i < lines.length; i++) {
                        leaves[i] = new LineLeaf(lines[i]);
                    }
                    this.root = LineIndex.buildTreeFromBottom(leaves);
                }
                else {
                    this.root = new LineNode();
                }
            };
            LineIndex.prototype.walk = function (rangeStart, rangeLength, walkFns) {
                this.root.walk(rangeStart, rangeLength, walkFns);
            };
            LineIndex.prototype.getText = function (rangeStart, rangeLength) {
                var accum = "";
                if ((rangeLength > 0) && (rangeStart < this.root.charCount())) {
                    this.walk(rangeStart, rangeLength, {
                        goSubtree: true,
                        done: false,
                        leaf: function (relativeStart, relativeLength, ll) {
                            accum = accum.concat(ll.text.substring(relativeStart, relativeStart + relativeLength));
                        }
                    });
                }
                return accum;
            };
            LineIndex.prototype.getLength = function () {
                return this.root.charCount();
            };
            LineIndex.prototype.every = function (f, rangeStart, rangeEnd) {
                if (!rangeEnd) {
                    rangeEnd = this.root.charCount();
                }
                var walkFns = {
                    goSubtree: true,
                    done: false,
                    leaf: function (relativeStart, relativeLength, ll) {
                        if (!f(ll, relativeStart, relativeLength)) {
                            this.done = true;
                        }
                    }
                };
                this.walk(rangeStart, rangeEnd - rangeStart, walkFns);
                return !walkFns.done;
            };
            LineIndex.prototype.edit = function (pos, deleteLength, newText) {
                if (this.root.charCount() === 0) {
                    ts.Debug.assert(deleteLength === 0); // Can't delete from empty document
                    if (newText !== undefined) {
                        this.load(LineIndex.linesFromText(newText).lines);
                        return this;
                    }
                    return undefined; // TODO: GH#18217
                }
                else {
                    var checkText = void 0;
                    if (this.checkEdits) {
                        var source = this.getText(0, this.root.charCount());
                        checkText = source.slice(0, pos) + newText + source.slice(pos + deleteLength);
                    }
                    var walker = new EditWalker();
                    var suppressTrailingText = false;
                    if (pos >= this.root.charCount()) {
                        // insert at end
                        pos = this.root.charCount() - 1;
                        var endString = this.getText(pos, 1);
                        if (newText) {
                            newText = endString + newText;
                        }
                        else {
                            newText = endString;
                        }
                        deleteLength = 0;
                        suppressTrailingText = true;
                    }
                    else if (deleteLength > 0) {
                        // check whether last characters deleted are line break
                        var e = pos + deleteLength;
                        var _a = this.positionToColumnAndLineText(e), zeroBasedColumn = _a.zeroBasedColumn, lineText = _a.lineText;
                        if (zeroBasedColumn === 0) {
                            // move range end just past line that will merge with previous line
                            deleteLength += lineText.length; // TODO: GH#18217
                            // store text by appending to end of insertedText
                            newText = newText ? newText + lineText : lineText;
                        }
                    }
                    this.root.walk(pos, deleteLength, walker);
                    walker.insertLines(newText, suppressTrailingText);
                    if (this.checkEdits) {
                        var updatedText = walker.lineIndex.getText(0, walker.lineIndex.getLength());
                        ts.Debug.assert(checkText === updatedText, "buffer edit mismatch");
                    }
                    return walker.lineIndex;
                }
            };
            LineIndex.buildTreeFromBottom = function (nodes) {
                if (nodes.length < lineCollectionCapacity) {
                    return new LineNode(nodes);
                }
                var interiorNodes = new Array(Math.ceil(nodes.length / lineCollectionCapacity));
                var nodeIndex = 0;
                for (var i = 0; i < interiorNodes.length; i++) {
                    var end = Math.min(nodeIndex + lineCollectionCapacity, nodes.length);
                    interiorNodes[i] = new LineNode(nodes.slice(nodeIndex, end));
                    nodeIndex = end;
                }
                return this.buildTreeFromBottom(interiorNodes);
            };
            LineIndex.linesFromText = function (text) {
                var lineMap = ts.computeLineStarts(text);
                if (lineMap.length === 0) {
                    return { lines: [], lineMap: lineMap };
                }
                var lines = new Array(lineMap.length);
                var lc = lineMap.length - 1;
                for (var lmi = 0; lmi < lc; lmi++) {
                    lines[lmi] = text.substring(lineMap[lmi], lineMap[lmi + 1]);
                }
                var endText = text.substring(lineMap[lc]);
                if (endText.length > 0) {
                    lines[lc] = endText;
                }
                else {
                    lines.pop();
                }
                return { lines: lines, lineMap: lineMap };
            };
            return LineIndex;
        }());
        server.LineIndex = LineIndex;
        var LineNode = /** @class */ (function () {
            function LineNode(children) {
                if (children === void 0) { children = []; }
                this.children = children;
                this.totalChars = 0;
                this.totalLines = 0;
                if (children.length)
                    this.updateCounts();
            }
            LineNode.prototype.isLeaf = function () {
                return false;
            };
            LineNode.prototype.updateCounts = function () {
                this.totalChars = 0;
                this.totalLines = 0;
                for (var _i = 0, _a = this.children; _i < _a.length; _i++) {
                    var child = _a[_i];
                    this.totalChars += child.charCount();
                    this.totalLines += child.lineCount();
                }
            };
            LineNode.prototype.execWalk = function (rangeStart, rangeLength, walkFns, childIndex, nodeType) {
                if (walkFns.pre) {
                    walkFns.pre(rangeStart, rangeLength, this.children[childIndex], this, nodeType);
                }
                if (walkFns.goSubtree) {
                    this.children[childIndex].walk(rangeStart, rangeLength, walkFns);
                    if (walkFns.post) {
                        walkFns.post(rangeStart, rangeLength, this.children[childIndex], this, nodeType);
                    }
                }
                else {
                    walkFns.goSubtree = true;
                }
                return walkFns.done;
            };
            LineNode.prototype.skipChild = function (relativeStart, relativeLength, childIndex, walkFns, nodeType) {
                if (walkFns.pre && (!walkFns.done)) {
                    walkFns.pre(relativeStart, relativeLength, this.children[childIndex], this, nodeType);
                    walkFns.goSubtree = true;
                }
            };
            LineNode.prototype.walk = function (rangeStart, rangeLength, walkFns) {
                // assume (rangeStart < this.totalChars) && (rangeLength <= this.totalChars)
                var childIndex = 0;
                var childCharCount = this.children[childIndex].charCount();
                // find sub-tree containing start
                var adjustedStart = rangeStart;
                while (adjustedStart >= childCharCount) {
                    this.skipChild(adjustedStart, rangeLength, childIndex, walkFns, 0 /* CharRangeSection.PreStart */);
                    adjustedStart -= childCharCount;
                    childIndex++;
                    childCharCount = this.children[childIndex].charCount();
                }
                // Case I: both start and end of range in same subtree
                if ((adjustedStart + rangeLength) <= childCharCount) {
                    if (this.execWalk(adjustedStart, rangeLength, walkFns, childIndex, 2 /* CharRangeSection.Entire */)) {
                        return;
                    }
                }
                else {
                    // Case II: start and end of range in different subtrees (possibly with subtrees in the middle)
                    if (this.execWalk(adjustedStart, childCharCount - adjustedStart, walkFns, childIndex, 1 /* CharRangeSection.Start */)) {
                        return;
                    }
                    var adjustedLength = rangeLength - (childCharCount - adjustedStart);
                    childIndex++;
                    var child = this.children[childIndex];
                    childCharCount = child.charCount();
                    while (adjustedLength > childCharCount) {
                        if (this.execWalk(0, childCharCount, walkFns, childIndex, 3 /* CharRangeSection.Mid */)) {
                            return;
                        }
                        adjustedLength -= childCharCount;
                        childIndex++;
                        childCharCount = this.children[childIndex].charCount();
                    }
                    if (adjustedLength > 0) {
                        if (this.execWalk(0, adjustedLength, walkFns, childIndex, 4 /* CharRangeSection.End */)) {
                            return;
                        }
                    }
                }
                // Process any subtrees after the one containing range end
                if (walkFns.pre) {
                    var clen = this.children.length;
                    if (childIndex < (clen - 1)) {
                        for (var ej = childIndex + 1; ej < clen; ej++) {
                            this.skipChild(0, 0, ej, walkFns, 5 /* CharRangeSection.PostEnd */);
                        }
                    }
                }
            };
            // Input position is relative to the start of this node.
            // Output line number is absolute.
            LineNode.prototype.charOffsetToLineInfo = function (lineNumberAccumulator, relativePosition) {
                if (this.children.length === 0) {
                    // Root node might have no children if this is an empty document.
                    return { oneBasedLine: lineNumberAccumulator, zeroBasedColumn: relativePosition, lineText: undefined };
                }
                for (var _i = 0, _a = this.children; _i < _a.length; _i++) {
                    var child = _a[_i];
                    if (child.charCount() > relativePosition) {
                        if (child.isLeaf()) {
                            return { oneBasedLine: lineNumberAccumulator, zeroBasedColumn: relativePosition, lineText: child.text };
                        }
                        else {
                            return child.charOffsetToLineInfo(lineNumberAccumulator, relativePosition);
                        }
                    }
                    else {
                        relativePosition -= child.charCount();
                        lineNumberAccumulator += child.lineCount();
                    }
                }
                // Skipped all children
                var lineCount = this.lineCount();
                if (lineCount === 0) { // it's empty! (and lineNumberToInfo expects a one-based line)
                    return { oneBasedLine: 1, zeroBasedColumn: 0, lineText: undefined };
                }
                var leaf = ts.Debug.checkDefined(this.lineNumberToInfo(lineCount, 0).leaf);
                return { oneBasedLine: lineCount, zeroBasedColumn: leaf.charCount(), lineText: undefined };
            };
            /**
             * Input line number is relative to the start of this node.
             * Output line number is relative to the child.
             * positionAccumulator will be an absolute position once relativeLineNumber reaches 0.
             */
            LineNode.prototype.lineNumberToInfo = function (relativeOneBasedLine, positionAccumulator) {
                for (var _i = 0, _a = this.children; _i < _a.length; _i++) {
                    var child = _a[_i];
                    var childLineCount = child.lineCount();
                    if (childLineCount >= relativeOneBasedLine) {
                        return child.isLeaf() ? { position: positionAccumulator, leaf: child } : child.lineNumberToInfo(relativeOneBasedLine, positionAccumulator);
                    }
                    else {
                        relativeOneBasedLine -= childLineCount;
                        positionAccumulator += child.charCount();
                    }
                }
                return { position: positionAccumulator, leaf: undefined };
            };
            LineNode.prototype.splitAfter = function (childIndex) {
                var splitNode;
                var clen = this.children.length;
                childIndex++;
                var endLength = childIndex;
                if (childIndex < clen) {
                    splitNode = new LineNode();
                    while (childIndex < clen) {
                        splitNode.add(this.children[childIndex]);
                        childIndex++;
                    }
                    splitNode.updateCounts();
                }
                this.children.length = endLength;
                return splitNode;
            };
            LineNode.prototype.remove = function (child) {
                var childIndex = this.findChildIndex(child);
                var clen = this.children.length;
                if (childIndex < (clen - 1)) {
                    for (var i = childIndex; i < (clen - 1); i++) {
                        this.children[i] = this.children[i + 1];
                    }
                }
                this.children.pop();
            };
            LineNode.prototype.findChildIndex = function (child) {
                var childIndex = this.children.indexOf(child);
                ts.Debug.assert(childIndex !== -1);
                return childIndex;
            };
            LineNode.prototype.insertAt = function (child, nodes) {
                var childIndex = this.findChildIndex(child);
                var clen = this.children.length;
                var nodeCount = nodes.length;
                // if child is last and there is more room and only one node to place, place it
                if ((clen < lineCollectionCapacity) && (childIndex === (clen - 1)) && (nodeCount === 1)) {
                    this.add(nodes[0]);
                    this.updateCounts();
                    return [];
                }
                else {
                    var shiftNode = this.splitAfter(childIndex);
                    var nodeIndex = 0;
                    childIndex++;
                    while ((childIndex < lineCollectionCapacity) && (nodeIndex < nodeCount)) {
                        this.children[childIndex] = nodes[nodeIndex];
                        childIndex++;
                        nodeIndex++;
                    }
                    var splitNodes = [];
                    var splitNodeCount = 0;
                    if (nodeIndex < nodeCount) {
                        splitNodeCount = Math.ceil((nodeCount - nodeIndex) / lineCollectionCapacity);
                        splitNodes = new Array(splitNodeCount);
                        var splitNodeIndex = 0;
                        for (var i = 0; i < splitNodeCount; i++) {
                            splitNodes[i] = new LineNode();
                        }
                        var splitNode = splitNodes[0];
                        while (nodeIndex < nodeCount) {
                            splitNode.add(nodes[nodeIndex]);
                            nodeIndex++;
                            if (splitNode.children.length === lineCollectionCapacity) {
                                splitNodeIndex++;
                                splitNode = splitNodes[splitNodeIndex];
                            }
                        }
                        for (var i = splitNodes.length - 1; i >= 0; i--) {
                            if (splitNodes[i].children.length === 0) {
                                splitNodes.pop();
                            }
                        }
                    }
                    if (shiftNode) {
                        splitNodes.push(shiftNode);
                    }
                    this.updateCounts();
                    for (var i = 0; i < splitNodeCount; i++) {
                        splitNodes[i].updateCounts();
                    }
                    return splitNodes;
                }
            };
            // assume there is room for the item; return true if more room
            LineNode.prototype.add = function (collection) {
                this.children.push(collection);
                ts.Debug.assert(this.children.length <= lineCollectionCapacity);
            };
            LineNode.prototype.charCount = function () {
                return this.totalChars;
            };
            LineNode.prototype.lineCount = function () {
                return this.totalLines;
            };
            return LineNode;
        }());
        var LineLeaf = /** @class */ (function () {
            function LineLeaf(text) {
                this.text = text;
            }
            LineLeaf.prototype.isLeaf = function () {
                return true;
            };
            LineLeaf.prototype.walk = function (rangeStart, rangeLength, walkFns) {
                walkFns.leaf(rangeStart, rangeLength, this);
            };
            LineLeaf.prototype.charCount = function () {
                return this.text.length;
            };
            LineLeaf.prototype.lineCount = function () {
                return 1;
            };
            return LineLeaf;
        }());
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/*@internal*/
var ts;
(function (ts) {
    var server;
    (function (server) {
        var BaseLogger = /** @class */ (function () {
            function BaseLogger(level) {
                this.level = level;
                this.seq = 0;
                this.inGroup = false;
                this.firstInGroup = true;
            }
            BaseLogger.padStringRight = function (str, padding) {
                return (str + padding).slice(0, padding.length);
            };
            BaseLogger.prototype.close = function () {
            };
            BaseLogger.prototype.getLogFileName = function () {
                return undefined;
            };
            BaseLogger.prototype.perftrc = function (s) {
                this.msg(s, server.Msg.Perf);
            };
            BaseLogger.prototype.info = function (s) {
                this.msg(s, server.Msg.Info);
            };
            BaseLogger.prototype.err = function (s) {
                this.msg(s, server.Msg.Err);
            };
            BaseLogger.prototype.startGroup = function () {
                this.inGroup = true;
                this.firstInGroup = true;
            };
            BaseLogger.prototype.endGroup = function () {
                this.inGroup = false;
            };
            BaseLogger.prototype.loggingEnabled = function () {
                return true;
            };
            BaseLogger.prototype.hasLevel = function (level) {
                return this.loggingEnabled() && this.level >= level;
            };
            BaseLogger.prototype.msg = function (s, type) {
                if (type === void 0) { type = server.Msg.Err; }
                switch (type) {
                    case server.Msg.Info:
                        ts.perfLogger.logInfoEvent(s);
                        break;
                    case server.Msg.Perf:
                        ts.perfLogger.logPerfEvent(s);
                        break;
                    default: // Msg.Err
                        ts.perfLogger.logErrEvent(s);
                        break;
                }
                if (!this.canWrite())
                    return;
                s = "[".concat(server.nowString(), "] ").concat(s, "\n");
                if (!this.inGroup || this.firstInGroup) {
                    var prefix = BaseLogger.padStringRight(type + " " + this.seq.toString(), "          ");
                    s = prefix + s;
                }
                this.write(s, type);
                if (!this.inGroup) {
                    this.seq++;
                }
            };
            BaseLogger.prototype.canWrite = function () {
                return true;
            };
            BaseLogger.prototype.write = function (_s, _type) {
            };
            return BaseLogger;
        }());
        server.BaseLogger = BaseLogger;
        var MainProcessLogger = /** @class */ (function (_super) {
            __extends(MainProcessLogger, _super);
            function MainProcessLogger(level, host) {
                var _this = _super.call(this, level) || this;
                _this.host = host;
                return _this;
            }
            MainProcessLogger.prototype.write = function (body, type) {
                var level;
                switch (type) {
                    case server.Msg.Info:
                        level = "info";
                        break;
                    case server.Msg.Perf:
                        level = "perf";
                        break;
                    case server.Msg.Err:
                        level = "error";
                        break;
                    default:
                        ts.Debug.assertNever(type);
                }
                this.host.writeMessage({
                    type: "log",
                    level: level,
                    body: body,
                });
            };
            return MainProcessLogger;
        }(BaseLogger));
        server.MainProcessLogger = MainProcessLogger;
        function createWebSystem(host, args, getExecutingFilePath) {
            var returnEmptyString = function () { return ""; };
            var getExecutingDirectoryPath = ts.memoize(function () { return ts.memoize(function () { return ts.ensureTrailingDirectorySeparator(ts.getDirectoryPath(getExecutingFilePath())); }); });
            // Later we could map ^memfs:/ to do something special if we want to enable more functionality like module resolution or something like that
            var getWebPath = function (path) { return ts.startsWith(path, ts.directorySeparator) ? path.replace(ts.directorySeparator, getExecutingDirectoryPath()) : undefined; };
            return {
                args: args,
                newLine: "\r\n",
                useCaseSensitiveFileNames: false,
                readFile: function (path) {
                    var webPath = getWebPath(path);
                    return webPath && host.readFile(webPath);
                },
                write: host.writeMessage.bind(host),
                watchFile: ts.returnNoopFileWatcher,
                watchDirectory: ts.returnNoopFileWatcher,
                getExecutingFilePath: function () { return ts.directorySeparator; },
                getCurrentDirectory: returnEmptyString,
                /* eslint-disable no-restricted-globals */
                setTimeout: function (cb, ms) {
                    var args = [];
                    for (var _i = 2; _i < arguments.length; _i++) {
                        args[_i - 2] = arguments[_i];
                    }
                    return setTimeout.apply(void 0, __spreadArray([cb, ms], args, false));
                },
                clearTimeout: function (handle) { return clearTimeout(handle); },
                setImmediate: function (x) { return setTimeout(x, 0); },
                clearImmediate: function (handle) { return clearTimeout(handle); },
                /* eslint-enable no-restricted-globals */
                require: function () { return ({ module: undefined, error: new Error("Not implemented") }); },
                exit: ts.notImplemented,
                // Debugging related
                getEnvironmentVariable: returnEmptyString,
                // tryEnableSourceMapsForHost?(): void;
                // debugMode?: boolean;
                // For semantic server mode
                fileExists: function (path) {
                    var webPath = getWebPath(path);
                    return !!webPath && host.fileExists(webPath);
                },
                directoryExists: ts.returnFalse,
                readDirectory: ts.notImplemented,
                getDirectories: function () { return []; },
                createDirectory: ts.notImplemented,
                writeFile: ts.notImplemented,
                resolvePath: ts.identity, // Plugins
                // realpath? // Module resolution, symlinks
                // getModifiedTime // File watching
                // createSHA256Hash // telemetry of the project
                // Logging related
                // /*@internal*/ bufferFrom?(input: string, encoding?: string): Buffer;
                // gc?(): void;
                // getMemoryUsage?(): number;
            };
        }
        server.createWebSystem = createWebSystem;
        var WorkerSession = /** @class */ (function (_super) {
            __extends(WorkerSession, _super);
            function WorkerSession(host, webHost, options, logger, cancellationToken, hrtime) {
                var _this = _super.call(this, __assign(__assign({ host: host, cancellationToken: cancellationToken }, options), { typingsInstaller: server.nullTypingsInstaller, byteLength: ts.notImplemented, // Formats the message text in send of Session which is overriden in this class so not needed
                    hrtime: hrtime, logger: logger, canUseEvents: true })) || this;
                _this.webHost = webHost;
                return _this;
            }
            WorkerSession.prototype.send = function (msg) {
                if (msg.type === "event" && !this.canUseEvents) {
                    if (this.logger.hasLevel(server.LogLevel.verbose)) {
                        this.logger.info("Session does not support events: ignored event: ".concat(JSON.stringify(msg)));
                    }
                    return;
                }
                if (this.logger.hasLevel(server.LogLevel.verbose)) {
                    this.logger.info("".concat(msg.type, ":").concat(server.indent(JSON.stringify(msg))));
                }
                this.webHost.writeMessage(msg);
            };
            WorkerSession.prototype.parseMessage = function (message) {
                return message;
            };
            WorkerSession.prototype.toStringMessage = function (message) {
                return JSON.stringify(message, undefined, 2);
            };
            return WorkerSession;
        }(server.Session));
        server.WorkerSession = WorkerSession;
    })(server = ts.server || (ts.server = {}));
})(ts || (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 = {}));
/*@internal*/
var ts;
(function (ts) {
    var server;
    (function (server) {
        function parseLoggingEnvironmentString(logEnvStr) {
            if (!logEnvStr) {
                return {};
            }
            var logEnv = { logToFile: true };
            var args = logEnvStr.split(" ");
            var len = args.length - 1;
            for (var i = 0; i < len; i += 2) {
                var option = args[i];
                var _a = getEntireValue(i + 1), value = _a.value, extraPartCounter = _a.extraPartCounter;
                i += extraPartCounter;
                if (option && value) {
                    switch (option) {
                        case "-file":
                            logEnv.file = value;
                            break;
                        case "-level":
                            var level = server.getLogLevel(value);
                            logEnv.detailLevel = level !== undefined ? level : server.LogLevel.normal;
                            break;
                        case "-traceToConsole":
                            logEnv.traceToConsole = value.toLowerCase() === "true";
                            break;
                        case "-logToFile":
                            logEnv.logToFile = value.toLowerCase() === "true";
                            break;
                    }
                }
            }
            return logEnv;
            function getEntireValue(initialIndex) {
                var pathStart = args[initialIndex];
                var extraPartCounter = 0;
                if (pathStart.charCodeAt(0) === 34 /* CharacterCodes.doubleQuote */ &&
                    pathStart.charCodeAt(pathStart.length - 1) !== 34 /* CharacterCodes.doubleQuote */) {
                    for (var i = initialIndex + 1; i < args.length; i++) {
                        pathStart += " ";
                        pathStart += args[i];
                        extraPartCounter++;
                        if (pathStart.charCodeAt(pathStart.length - 1) === 34 /* CharacterCodes.doubleQuote */)
                            break;
                    }
                }
                return { value: ts.stripQuotes(pathStart), extraPartCounter: extraPartCounter };
            }
        }
        function parseServerMode() {
            var mode = server.findArgument("--serverMode");
            if (!mode)
                return undefined;
            switch (mode.toLowerCase()) {
                case "semantic":
                    return ts.LanguageServiceMode.Semantic;
                case "partialsemantic":
                    return ts.LanguageServiceMode.PartialSemantic;
                case "syntactic":
                    return ts.LanguageServiceMode.Syntactic;
                default:
                    return mode;
            }
        }
        function initializeNodeSystem() {
            var sys = ts.Debug.checkDefined(ts.sys);
            var childProcess = require("child_process");
            var fs = require("fs");
            var Logger = /** @class */ (function (_super) {
                __extends(Logger, _super);
                function Logger(logFilename, traceToConsole, level) {
                    var _this = _super.call(this, level) || this;
                    _this.logFilename = logFilename;
                    _this.traceToConsole = traceToConsole;
                    _this.fd = -1;
                    if (_this.logFilename) {
                        try {
                            _this.fd = fs.openSync(_this.logFilename, "w");
                        }
                        catch (_) {
                            // swallow the error and keep logging disabled if file cannot be opened
                        }
                    }
                    return _this;
                }
                Logger.prototype.close = function () {
                    if (this.fd >= 0) {
                        fs.close(this.fd, ts.noop);
                    }
                };
                Logger.prototype.getLogFileName = function () {
                    return this.logFilename;
                };
                Logger.prototype.loggingEnabled = function () {
                    return !!this.logFilename || this.traceToConsole;
                };
                Logger.prototype.canWrite = function () {
                    return this.fd >= 0 || this.traceToConsole;
                };
                Logger.prototype.write = function (s, _type) {
                    if (this.fd >= 0) {
                        var buf = sys.bufferFrom(s);
                        // eslint-disable-next-line no-null/no-null
                        fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null); // TODO: GH#18217
                    }
                    if (this.traceToConsole) {
                        console.warn(s);
                    }
                };
                return Logger;
            }(server.BaseLogger));
            var nodeVersion = ts.getNodeMajorVersion();
            // use watchGuard process on Windows when node version is 4 or later
            var useWatchGuard = process.platform === "win32" && nodeVersion >= 4;
            var originalWatchDirectory = sys.watchDirectory.bind(sys);
            var logger = createLogger();
            var pending = [];
            var canWrite = true;
            if (useWatchGuard) {
                var currentDrive_1 = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), /*currentDriveKey*/ undefined);
                var statusCache_1 = new ts.Map();
                sys.watchDirectory = function (path, callback, recursive, options) {
                    var cacheKey = extractWatchDirectoryCacheKey(path, currentDrive_1);
                    var status = cacheKey && statusCache_1.get(cacheKey);
                    if (status === undefined) {
                        if (logger.hasLevel(server.LogLevel.verbose)) {
                            logger.info("".concat(cacheKey, " for path ").concat(path, " not found in cache..."));
                        }
                        try {
                            var args = [ts.combinePaths(__dirname, "watchGuard.js"), path];
                            if (logger.hasLevel(server.LogLevel.verbose)) {
                                logger.info("Starting ".concat(process.execPath, " with args:").concat(server.stringifyIndented(args)));
                            }
                            childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { ELECTRON_RUN_AS_NODE: "1" } });
                            status = true;
                            if (logger.hasLevel(server.LogLevel.verbose)) {
                                logger.info("WatchGuard for path ".concat(path, " returned: OK"));
                            }
                        }
                        catch (e) {
                            status = false;
                            if (logger.hasLevel(server.LogLevel.verbose)) {
                                logger.info("WatchGuard for path ".concat(path, " returned: ").concat(e.message));
                            }
                        }
                        if (cacheKey) {
                            statusCache_1.set(cacheKey, status);
                        }
                    }
                    else if (logger.hasLevel(server.LogLevel.verbose)) {
                        logger.info("watchDirectory for ".concat(path, " uses cached drive information."));
                    }
                    if (status) {
                        // this drive is safe to use - call real 'watchDirectory'
                        return watchDirectorySwallowingException(path, callback, recursive, options);
                    }
                    else {
                        // this drive is unsafe - return no-op watcher
                        return ts.noopFileWatcher;
                    }
                };
            }
            else {
                sys.watchDirectory = watchDirectorySwallowingException;
            }
            // Override sys.write because fs.writeSync is not reliable on Node 4
            sys.write = function (s) { return writeMessage(sys.bufferFrom(s, "utf8")); };
            // REVIEW: for now this implementation uses polling.
            // The advantage of polling is that it works reliably
            // on all os and with network mounted files.
            // For 90 referenced files, the average time to detect
            // changes is 2*msInterval (by default 5 seconds).
            // The overhead of this is .04 percent (1/2500) with
            // average pause of < 1 millisecond (and max
            // pause less than 1.5 milliseconds); question is
            // do we anticipate reference sets in the 100s and
            // do we care about waiting 10-20 seconds to detect
            // changes for large reference sets? If so, do we want
            // to increase the chunk size or decrease the interval
            // time dynamically to match the large reference set?
            sys.defaultWatchFileKind = function () { return ts.WatchFileKind.FixedChunkSizePolling; };
            /* eslint-disable no-restricted-globals */
            sys.setTimeout = setTimeout;
            sys.clearTimeout = clearTimeout;
            sys.setImmediate = setImmediate;
            sys.clearImmediate = clearImmediate;
            /* eslint-enable no-restricted-globals */
            if (typeof global !== "undefined" && global.gc) {
                sys.gc = function () { var _a; return (_a = global.gc) === null || _a === void 0 ? void 0 : _a.call(global); };
            }
            sys.require = function (initialDir, moduleName) {
                try {
                    return { module: require(ts.resolveJSModule(moduleName, initialDir, sys)), error: undefined };
                }
                catch (error) {
                    return { module: undefined, error: error };
                }
            };
            var cancellationToken;
            try {
                var factory_1 = require("./cancellationToken");
                cancellationToken = factory_1(sys.args);
            }
            catch (e) {
                cancellationToken = server.nullCancellationToken;
            }
            var localeStr = server.findArgument("--locale");
            if (localeStr) {
                ts.validateLocaleAndSetLanguage(localeStr, sys);
            }
            var modeOrUnknown = parseServerMode();
            var serverMode;
            var unknownServerMode;
            if (modeOrUnknown !== undefined) {
                if (typeof modeOrUnknown === "number")
                    serverMode = modeOrUnknown;
                else
                    unknownServerMode = modeOrUnknown;
            }
            return {
                args: process.argv,
                logger: logger,
                cancellationToken: cancellationToken,
                serverMode: serverMode,
                unknownServerMode: unknownServerMode,
                startSession: startNodeSession
            };
            // TSS_LOG "{ level: "normal | verbose | terse", file?: string}"
            function createLogger() {
                var cmdLineLogFileName = server.findArgument("--logFile");
                var cmdLineVerbosity = server.getLogLevel(server.findArgument("--logVerbosity"));
                var envLogOptions = parseLoggingEnvironmentString(process.env.TSS_LOG);
                var unsubstitutedLogFileName = cmdLineLogFileName
                    ? ts.stripQuotes(cmdLineLogFileName)
                    : envLogOptions.logToFile
                        ? envLogOptions.file || (__dirname + "/.log" + process.pid.toString())
                        : undefined;
                var substitutedLogFileName = unsubstitutedLogFileName
                    ? unsubstitutedLogFileName.replace("PID", process.pid.toString())
                    : undefined;
                var logVerbosity = cmdLineVerbosity || envLogOptions.detailLevel;
                return new Logger(substitutedLogFileName, envLogOptions.traceToConsole, logVerbosity); // TODO: GH#18217
            }
            function writeMessage(buf) {
                if (!canWrite) {
                    pending.push(buf);
                }
                else {
                    canWrite = false;
                    process.stdout.write(buf, setCanWriteFlagAndWriteMessageIfNecessary);
                }
            }
            function setCanWriteFlagAndWriteMessageIfNecessary() {
                canWrite = true;
                if (pending.length) {
                    writeMessage(pending.shift());
                }
            }
            function extractWatchDirectoryCacheKey(path, currentDriveKey) {
                path = ts.normalizeSlashes(path);
                if (isUNCPath(path)) {
                    // UNC path: extract server name
                    // //server/location
                    //         ^ <- from 0 to this position
                    var firstSlash = path.indexOf(ts.directorySeparator, 2);
                    return firstSlash !== -1 ? ts.toFileNameLowerCase(path.substring(0, firstSlash)) : path;
                }
                var rootLength = ts.getRootLength(path);
                if (rootLength === 0) {
                    // relative path - assume file is on the current drive
                    return currentDriveKey;
                }
                if (path.charCodeAt(1) === 58 /* CharacterCodes.colon */ && path.charCodeAt(2) === 47 /* CharacterCodes.slash */) {
                    // rooted path that starts with c:/... - extract drive letter
                    return ts.toFileNameLowerCase(path.charAt(0));
                }
                if (path.charCodeAt(0) === 47 /* CharacterCodes.slash */ && path.charCodeAt(1) !== 47 /* CharacterCodes.slash */) {
                    // rooted path that starts with slash - /somename - use key for current drive
                    return currentDriveKey;
                }
                // do not cache any other cases
                return undefined;
            }
            function isUNCPath(s) {
                return s.length > 2 && s.charCodeAt(0) === 47 /* CharacterCodes.slash */ && s.charCodeAt(1) === 47 /* CharacterCodes.slash */;
            }
            // This is the function that catches the exceptions when watching directory, and yet lets project service continue to function
            // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point
            function watchDirectorySwallowingException(path, callback, recursive, options) {
                try {
                    return originalWatchDirectory(path, callback, recursive, options);
                }
                catch (e) {
                    logger.info("Exception when creating directory watcher: ".concat(e.message));
                    return ts.noopFileWatcher;
                }
            }
        }
        server.initializeNodeSystem = initializeNodeSystem;
        function parseEventPort(eventPortStr) {
            var eventPort = eventPortStr === undefined ? undefined : parseInt(eventPortStr);
            return eventPort !== undefined && !isNaN(eventPort) ? eventPort : undefined;
        }
        function startNodeSession(options, logger, cancellationToken) {
            var childProcess = require("child_process");
            var os = require("os");
            var net = require("net");
            var readline = require("readline");
            var rl = readline.createInterface({
                input: process.stdin,
                output: process.stdout,
                terminal: false,
            });
            var NodeTypingsInstaller = /** @class */ (function () {
                function NodeTypingsInstaller(telemetryEnabled, logger, host, globalTypingsCacheLocation, typingSafeListLocation, typesMapLocation, npmLocation, validateDefaultNpmLocation, event) {
                    this.telemetryEnabled = telemetryEnabled;
                    this.logger = logger;
                    this.host = host;
                    this.globalTypingsCacheLocation = globalTypingsCacheLocation;
                    this.typingSafeListLocation = typingSafeListLocation;
                    this.typesMapLocation = typesMapLocation;
                    this.npmLocation = npmLocation;
                    this.validateDefaultNpmLocation = validateDefaultNpmLocation;
                    this.event = event;
                    this.activeRequestCount = 0;
                    this.requestQueue = [];
                    this.requestMap = new ts.Map(); // Maps operation ID to newest requestQueue entry with that ID
                    /** We will lazily request the types registry on the first call to `isKnownTypesPackageName` and store it in `typesRegistryCache`. */
                    this.requestedRegistry = false;
                }
                NodeTypingsInstaller.prototype.isKnownTypesPackageName = function (name) {
                    // We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package.
                    var validationResult = ts.JsTyping.validatePackageName(name);
                    if (validationResult !== 0 /* JsTyping.NameValidationResult.Ok */) {
                        return false;
                    }
                    if (this.requestedRegistry) {
                        return !!this.typesRegistryCache && this.typesRegistryCache.has(name);
                    }
                    this.requestedRegistry = true;
                    this.send({ kind: "typesRegistry" });
                    return false;
                };
                NodeTypingsInstaller.prototype.installPackage = function (options) {
                    var _this = this;
                    this.send(__assign({ kind: "installPackage" }, options));
                    ts.Debug.assert(this.packageInstalledPromise === undefined);
                    return new Promise(function (resolve, reject) {
                        _this.packageInstalledPromise = { resolve: resolve, reject: reject };
                    });
                };
                NodeTypingsInstaller.prototype.attach = function (projectService) {
                    var _this = this;
                    this.projectService = projectService;
                    if (this.logger.hasLevel(server.LogLevel.requestTime)) {
                        this.logger.info("Binding...");
                    }
                    var args = [server.Arguments.GlobalCacheLocation, this.globalTypingsCacheLocation];
                    if (this.telemetryEnabled) {
                        args.push(server.Arguments.EnableTelemetry);
                    }
                    if (this.logger.loggingEnabled() && this.logger.getLogFileName()) {
                        args.push(server.Arguments.LogFile, ts.combinePaths(ts.getDirectoryPath(ts.normalizeSlashes(this.logger.getLogFileName())), "ti-".concat(process.pid, ".log")));
                    }
                    if (this.typingSafeListLocation) {
                        args.push(server.Arguments.TypingSafeListLocation, this.typingSafeListLocation);
                    }
                    if (this.typesMapLocation) {
                        args.push(server.Arguments.TypesMapLocation, this.typesMapLocation);
                    }
                    if (this.npmLocation) {
                        args.push(server.Arguments.NpmLocation, this.npmLocation);
                    }
                    if (this.validateDefaultNpmLocation) {
                        args.push(server.Arguments.ValidateDefaultNpmLocation);
                    }
                    var execArgv = [];
                    for (var _i = 0, _a = process.execArgv; _i < _a.length; _i++) {
                        var arg = _a[_i];
                        var match = /^--((?:debug|inspect)(?:-brk)?)(?:=(\d+))?$/.exec(arg);
                        if (match) {
                            // if port is specified - use port + 1
                            // otherwise pick a default port depending on if 'debug' or 'inspect' and use its value + 1
                            var currentPort = match[2] !== undefined
                                ? +match[2]
                                : match[1].charAt(0) === "d" ? 5858 : 9229;
                            execArgv.push("--".concat(match[1], "=").concat(currentPort + 1));
                            break;
                        }
                    }
                    this.installer = childProcess.fork(ts.combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv: execArgv });
                    this.installer.on("message", function (m) { return _this.handleMessage(m); });
                    // We have to schedule this event to the next tick
                    // cause this fn will be called during
                    // new IOSession => super(which is Session) => new ProjectService => NodeTypingsInstaller.attach
                    // and if "event" is referencing "this" before super class is initialized, it will be a ReferenceError in ES6 class.
                    this.host.setImmediate(function () { return _this.event({ pid: _this.installer.pid }, "typingsInstallerPid"); });
                    process.on("exit", function () {
                        _this.installer.kill();
                    });
                };
                NodeTypingsInstaller.prototype.onProjectClosed = function (p) {
                    this.send({ projectName: p.getProjectName(), kind: "closeProject" });
                };
                NodeTypingsInstaller.prototype.send = function (rq) {
                    this.installer.send(rq);
                };
                NodeTypingsInstaller.prototype.enqueueInstallTypingsRequest = function (project, typeAcquisition, unresolvedImports) {
                    var _this = this;
                    var request = server.createInstallTypingsRequest(project, typeAcquisition, unresolvedImports);
                    if (this.logger.hasLevel(server.LogLevel.verbose)) {
                        if (this.logger.hasLevel(server.LogLevel.verbose)) {
                            this.logger.info("Scheduling throttled operation:".concat(server.stringifyIndented(request)));
                        }
                    }
                    var operationId = project.getProjectName();
                    var operation = function () {
                        if (_this.logger.hasLevel(server.LogLevel.verbose)) {
                            _this.logger.info("Sending request:".concat(server.stringifyIndented(request)));
                        }
                        _this.send(request);
                    };
                    var queuedRequest = { operationId: operationId, operation: operation };
                    if (this.activeRequestCount < NodeTypingsInstaller.maxActiveRequestCount) {
                        this.scheduleRequest(queuedRequest);
                    }
                    else {
                        if (this.logger.hasLevel(server.LogLevel.verbose)) {
                            this.logger.info("Deferring request for: ".concat(operationId));
                        }
                        this.requestQueue.push(queuedRequest);
                        this.requestMap.set(operationId, queuedRequest);
                    }
                };
                NodeTypingsInstaller.prototype.handleMessage = function (response) {
                    if (this.logger.hasLevel(server.LogLevel.verbose)) {
                        this.logger.info("Received response:".concat(server.stringifyIndented(response)));
                    }
                    switch (response.kind) {
                        case server.EventTypesRegistry:
                            this.typesRegistryCache = new ts.Map(ts.getEntries(response.typesRegistry));
                            break;
                        case server.ActionPackageInstalled: {
                            var success = response.success, message = response.message;
                            if (success) {
                                this.packageInstalledPromise.resolve({ successMessage: message });
                            }
                            else {
                                this.packageInstalledPromise.reject(message);
                            }
                            this.packageInstalledPromise = undefined;
                            this.projectService.updateTypingsForProject(response);
                            // The behavior is the same as for setTypings, so send the same event.
                            this.event(response, "setTypings");
                            break;
                        }
                        case server.EventInitializationFailed: {
                            var body = {
                                message: response.message
                            };
                            var eventName = "typesInstallerInitializationFailed";
                            this.event(body, eventName);
                            break;
                        }
                        case server.EventBeginInstallTypes: {
                            var body = {
                                eventId: response.eventId,
                                packages: response.packagesToInstall,
                            };
                            var eventName = "beginInstallTypes";
                            this.event(body, eventName);
                            break;
                        }
                        case server.EventEndInstallTypes: {
                            if (this.telemetryEnabled) {
                                var body_1 = {
                                    telemetryEventName: "typingsInstalled",
                                    payload: {
                                        installedPackages: response.packagesToInstall.join(","),
                                        installSuccess: response.installSuccess,
                                        typingsInstallerVersion: response.typingsInstallerVersion
                                    }
                                };
                                var eventName_1 = "telemetry";
                                this.event(body_1, eventName_1);
                            }
                            var body = {
                                eventId: response.eventId,
                                packages: response.packagesToInstall,
                                success: response.installSuccess,
                            };
                            var eventName = "endInstallTypes";
                            this.event(body, eventName);
                            break;
                        }
                        case server.ActionInvalidate: {
                            this.projectService.updateTypingsForProject(response);
                            break;
                        }
                        case server.ActionSet: {
                            if (this.activeRequestCount > 0) {
                                this.activeRequestCount--;
                            }
                            else {
                                ts.Debug.fail("Received too many responses");
                            }
                            while (this.requestQueue.length > 0) {
                                var queuedRequest = this.requestQueue.shift();
                                if (this.requestMap.get(queuedRequest.operationId) === queuedRequest) {
                                    this.requestMap.delete(queuedRequest.operationId);
                                    this.scheduleRequest(queuedRequest);
                                    break;
                                }
                                if (this.logger.hasLevel(server.LogLevel.verbose)) {
                                    this.logger.info("Skipping defunct request for: ".concat(queuedRequest.operationId));
                                }
                            }
                            this.projectService.updateTypingsForProject(response);
                            this.event(response, "setTypings");
                            break;
                        }
                        default:
                            ts.assertType(response);
                    }
                };
                NodeTypingsInstaller.prototype.scheduleRequest = function (request) {
                    if (this.logger.hasLevel(server.LogLevel.verbose)) {
                        this.logger.info("Scheduling request for: ".concat(request.operationId));
                    }
                    this.activeRequestCount++;
                    this.host.setTimeout(request.operation, NodeTypingsInstaller.requestDelayMillis);
                };
                // This number is essentially arbitrary.  Processing more than one typings request
                // at a time makes sense, but having too many in the pipe results in a hang
                // (see https://github.com/nodejs/node/issues/7657).
                // It would be preferable to base our limit on the amount of space left in the
                // buffer, but we have yet to find a way to retrieve that value.
                NodeTypingsInstaller.maxActiveRequestCount = 10;
                NodeTypingsInstaller.requestDelayMillis = 100;
                return NodeTypingsInstaller;
            }());
            var IOSession = /** @class */ (function (_super) {
                __extends(IOSession, _super);
                function IOSession() {
                    var _this = this;
                    var event = function (body, eventName) {
                        _this.event(body, eventName);
                    };
                    var host = ts.sys;
                    var typingsInstaller = disableAutomaticTypingAcquisition
                        ? undefined
                        : new NodeTypingsInstaller(telemetryEnabled, logger, host, getGlobalTypingsCacheLocation(), typingSafeListLocation, typesMapLocation, npmLocation, validateDefaultNpmLocation, event);
                    _this = _super.call(this, __assign(__assign({ host: host, cancellationToken: cancellationToken }, options), { typingsInstaller: typingsInstaller || server.nullTypingsInstaller, byteLength: Buffer.byteLength, hrtime: process.hrtime, logger: logger, canUseEvents: true, typesMapLocation: typesMapLocation })) || this;
                    _this.eventPort = eventPort;
                    if (_this.canUseEvents && _this.eventPort) {
                        var s_1 = net.connect({ port: _this.eventPort }, function () {
                            _this.eventSocket = s_1;
                            if (_this.socketEventQueue) {
                                // flush queue.
                                for (var _i = 0, _a = _this.socketEventQueue; _i < _a.length; _i++) {
                                    var event_1 = _a[_i];
                                    _this.writeToEventSocket(event_1.body, event_1.eventName);
                                }
                                _this.socketEventQueue = undefined;
                            }
                        });
                    }
                    _this.constructed = true;
                    return _this;
                }
                IOSession.prototype.event = function (body, eventName) {
                    ts.Debug.assert(!!this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession");
                    if (this.canUseEvents && this.eventPort) {
                        if (!this.eventSocket) {
                            if (this.logger.hasLevel(server.LogLevel.verbose)) {
                                this.logger.info("eventPort: event \"".concat(eventName, "\" queued, but socket not yet initialized"));
                            }
                            (this.socketEventQueue || (this.socketEventQueue = [])).push({ body: body, eventName: eventName });
                            return;
                        }
                        else {
                            ts.Debug.assert(this.socketEventQueue === undefined);
                            this.writeToEventSocket(body, eventName);
                        }
                    }
                    else {
                        _super.prototype.event.call(this, body, eventName);
                    }
                };
                IOSession.prototype.writeToEventSocket = function (body, eventName) {
                    this.eventSocket.write(server.formatMessage(server.toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8");
                };
                IOSession.prototype.exit = function () {
                    this.logger.info("Exiting...");
                    this.projectService.closeLog();
                    ts.tracing === null || ts.tracing === void 0 ? void 0 : ts.tracing.stopTracing();
                    process.exit(0);
                };
                IOSession.prototype.listen = function () {
                    var _this = this;
                    rl.on("line", function (input) {
                        var message = input.trim();
                        _this.onMessage(message);
                    });
                    rl.on("close", function () {
                        _this.exit();
                    });
                };
                return IOSession;
            }(server.Session));
            var IpcIOSession = /** @class */ (function (_super) {
                __extends(IpcIOSession, _super);
                function IpcIOSession() {
                    return _super !== null && _super.apply(this, arguments) || this;
                }
                IpcIOSession.prototype.writeMessage = function (msg) {
                    var verboseLogging = logger.hasLevel(server.LogLevel.verbose);
                    if (verboseLogging) {
                        var json = JSON.stringify(msg);
                        logger.info("".concat(msg.type, ":").concat(server.indent(json)));
                    }
                    process.send(msg);
                };
                IpcIOSession.prototype.parseMessage = function (message) {
                    return message;
                };
                IpcIOSession.prototype.toStringMessage = function (message) {
                    return JSON.stringify(message, undefined, 2);
                };
                IpcIOSession.prototype.listen = function () {
                    var _this = this;
                    process.on("message", function (e) {
                        _this.onMessage(e);
                    });
                };
                return IpcIOSession;
            }(IOSession));
            var eventPort = parseEventPort(server.findArgument("--eventPort"));
            var typingSafeListLocation = server.findArgument(server.Arguments.TypingSafeListLocation); // TODO: GH#18217
            var typesMapLocation = server.findArgument(server.Arguments.TypesMapLocation) || ts.combinePaths(ts.getDirectoryPath(ts.sys.getExecutingFilePath()), "typesMap.json");
            var npmLocation = server.findArgument(server.Arguments.NpmLocation);
            var validateDefaultNpmLocation = server.hasArgument(server.Arguments.ValidateDefaultNpmLocation);
            var disableAutomaticTypingAcquisition = server.hasArgument("--disableAutomaticTypingAcquisition");
            var useNodeIpc = server.hasArgument("--useNodeIpc");
            var telemetryEnabled = server.hasArgument(server.Arguments.EnableTelemetry);
            var commandLineTraceDir = server.findArgument("--traceDirectory");
            var traceDir = commandLineTraceDir
                ? ts.stripQuotes(commandLineTraceDir)
                : process.env.TSS_TRACE;
            if (traceDir) {
                ts.startTracing("server", traceDir);
            }
            var ioSession = useNodeIpc ? new IpcIOSession() : new IOSession();
            process.on("uncaughtException", function (err) {
                ioSession.logError(err, "unknown");
            });
            // See https://github.com/Microsoft/TypeScript/issues/11348
            process.noAsar = true;
            // Start listening
            ioSession.listen();
            function getGlobalTypingsCacheLocation() {
                switch (process.platform) {
                    case "win32": {
                        var basePath = process.env.LOCALAPPDATA ||
                            process.env.APPDATA ||
                            (os.homedir && os.homedir()) ||
                            process.env.USERPROFILE ||
                            (process.env.HOMEDRIVE && process.env.HOMEPATH && ts.normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) ||
                            os.tmpdir();
                        return ts.combinePaths(ts.combinePaths(ts.normalizeSlashes(basePath), "Microsoft/TypeScript"), ts.versionMajorMinor);
                    }
                    case "openbsd":
                    case "freebsd":
                    case "netbsd":
                    case "darwin":
                    case "linux":
                    case "android": {
                        var cacheLocation = getNonWindowsCacheLocation(process.platform === "darwin");
                        return ts.combinePaths(ts.combinePaths(cacheLocation, "typescript"), ts.versionMajorMinor);
                    }
                    default:
                        return ts.Debug.fail("unsupported platform '".concat(process.platform, "'"));
                }
            }
            function getNonWindowsCacheLocation(platformIsDarwin) {
                if (process.env.XDG_CACHE_HOME) {
                    return process.env.XDG_CACHE_HOME;
                }
                var usersDir = platformIsDarwin ? "Users" : "home";
                var homePath = (os.homedir && os.homedir()) ||
                    process.env.HOME ||
                    ((process.env.LOGNAME || process.env.USER) && "/".concat(usersDir, "/").concat(process.env.LOGNAME || process.env.USER)) ||
                    os.tmpdir();
                var cacheFolder = platformIsDarwin
                    ? "Library/Caches"
                    : ".cache";
                return ts.combinePaths(ts.normalizeSlashes(homePath), cacheFolder);
            }
        }
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/*@internal*/
/// <reference lib="webworker" />
var ts;
(function (ts) {
    var server;
    (function (server) {
        var nullLogger = {
            close: ts.noop,
            hasLevel: ts.returnFalse,
            loggingEnabled: ts.returnFalse,
            perftrc: ts.noop,
            info: ts.noop,
            msg: ts.noop,
            startGroup: ts.noop,
            endGroup: ts.noop,
            getLogFileName: ts.returnUndefined,
        };
        function parseServerMode() {
            var mode = server.findArgument("--serverMode");
            if (!mode)
                return undefined;
            switch (mode.toLowerCase()) {
                case "partialsemantic":
                    return ts.LanguageServiceMode.PartialSemantic;
                case "syntactic":
                    return ts.LanguageServiceMode.Syntactic;
                default:
                    return mode;
            }
        }
        function initializeWebSystem(args) {
            createWebSystem(args);
            var modeOrUnknown = parseServerMode();
            var serverMode;
            var unknownServerMode;
            if (typeof modeOrUnknown === "number")
                serverMode = modeOrUnknown;
            else
                unknownServerMode = modeOrUnknown;
            return {
                args: args,
                logger: createLogger(),
                cancellationToken: server.nullCancellationToken,
                // Webserver defaults to partial semantic mode
                serverMode: serverMode !== null && serverMode !== void 0 ? serverMode : ts.LanguageServiceMode.PartialSemantic,
                unknownServerMode: unknownServerMode,
                startSession: startWebSession
            };
        }
        server.initializeWebSystem = initializeWebSystem;
        function createLogger() {
            var cmdLineVerbosity = server.getLogLevel(server.findArgument("--logVerbosity"));
            return cmdLineVerbosity !== undefined ? new server.MainProcessLogger(cmdLineVerbosity, { writeMessage: writeMessage }) : nullLogger;
        }
        function writeMessage(s) {
            postMessage(s);
        }
        function createWebSystem(args) {
            ts.Debug.assert(ts.sys === undefined);
            var webHost = {
                readFile: function (webPath) {
                    var request = new XMLHttpRequest();
                    request.open("GET", webPath, /* asynchronous */ false);
                    request.send();
                    return request.status === 200 ? request.responseText : undefined;
                },
                fileExists: function (webPath) {
                    var request = new XMLHttpRequest();
                    request.open("HEAD", webPath, /* asynchronous */ false);
                    request.send();
                    return request.status === 200;
                },
                writeMessage: writeMessage,
            };
            // Do this after sys has been set as findArguments is going to work only then
            var sys = server.createWebSystem(webHost, args, function () { return server.findArgument("--executingFilePath") || location + ""; });
            ts.setSys(sys);
            var localeStr = server.findArgument("--locale");
            if (localeStr) {
                ts.validateLocaleAndSetLanguage(localeStr, sys);
            }
        }
        function hrtime(previous) {
            var now = self.performance.now() * 1e-3;
            var seconds = Math.floor(now);
            var nanoseconds = Math.floor((now % 1) * 1e9);
            if (previous) {
                seconds = seconds - previous[0];
                nanoseconds = nanoseconds - previous[1];
                if (nanoseconds < 0) {
                    seconds--;
                    nanoseconds += 1e9;
                }
            }
            return [seconds, nanoseconds];
        }
        function startWebSession(options, logger, cancellationToken) {
            var WorkerSession = /** @class */ (function (_super) {
                __extends(WorkerSession, _super);
                function WorkerSession() {
                    return _super.call(this, ts.sys, { writeMessage: writeMessage }, options, logger, cancellationToken, hrtime) || this;
                }
                WorkerSession.prototype.exit = function () {
                    this.logger.info("Exiting...");
                    this.projectService.closeLog();
                    close();
                };
                WorkerSession.prototype.listen = function () {
                    var _this = this;
                    addEventListener("message", function (message) {
                        _this.onMessage(message.data);
                    });
                };
                return WorkerSession;
            }(server.WorkerSession));
            var session = new WorkerSession();
            // Start listening
            session.listen();
        }
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
/*@internal*/
var ts;
(function (ts) {
    var server;
    (function (server) {
        function findArgumentStringArray(argName) {
            var arg = server.findArgument(argName);
            if (arg === undefined) {
                return server.emptyArray;
            }
            return arg.split(",").filter(function (name) { return name !== ""; });
        }
        function getLogLevel(level) {
            if (level) {
                var l = level.toLowerCase();
                for (var name_1 in server.LogLevel) {
                    if (isNaN(+name_1) && l === name_1.toLowerCase()) {
                        return server.LogLevel[name_1];
                    }
                }
            }
            return undefined;
        }
        server.getLogLevel = getLogLevel;
        function start(_a, platform) {
            var args = _a.args, logger = _a.logger, cancellationToken = _a.cancellationToken, serverMode = _a.serverMode, unknownServerMode = _a.unknownServerMode, startServer = _a.startSession;
            var syntaxOnly = server.hasArgument("--syntaxOnly");
            logger.info("Starting TS Server");
            logger.info("Version: ".concat(ts.version));
            logger.info("Arguments: ".concat(args.join(" ")));
            logger.info("Platform: ".concat(platform, " NodeVersion: ").concat(ts.getNodeMajorVersion(), " CaseSensitive: ").concat(ts.sys.useCaseSensitiveFileNames));
            logger.info("ServerMode: ".concat(serverMode, " syntaxOnly: ").concat(syntaxOnly, " hasUnknownServerMode: ").concat(unknownServerMode));
            ts.setStackTraceLimit();
            if (ts.Debug.isDebugging) {
                ts.Debug.enableDebugInfo();
            }
            if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
                ts.sys.tryEnableSourceMapsForHost();
            }
            // Overwrites the current console messages to instead write to
            // the log. This is so that language service plugins which use
            // console.log don't break the message passing between tsserver
            // and the client
            console.log = function () {
                var args = [];
                for (var _i = 0; _i < arguments.length; _i++) {
                    args[_i] = arguments[_i];
                }
                return logger.msg(args.length === 1 ? args[0] : args.join(", "), server.Msg.Info);
            };
            console.warn = function () {
                var args = [];
                for (var _i = 0; _i < arguments.length; _i++) {
                    args[_i] = arguments[_i];
                }
                return logger.msg(args.length === 1 ? args[0] : args.join(", "), server.Msg.Err);
            };
            console.error = function () {
                var args = [];
                for (var _i = 0; _i < arguments.length; _i++) {
                    args[_i] = arguments[_i];
                }
                return logger.msg(args.length === 1 ? args[0] : args.join(", "), server.Msg.Err);
            };
            startServer({
                globalPlugins: findArgumentStringArray("--globalPlugins"),
                pluginProbeLocations: findArgumentStringArray("--pluginProbeLocations"),
                allowLocalPluginLoads: server.hasArgument("--allowLocalPluginLoads"),
                useSingleInferredProject: server.hasArgument("--useSingleInferredProject"),
                useInferredProjectPerProjectRoot: server.hasArgument("--useInferredProjectPerProjectRoot"),
                suppressDiagnosticEvents: server.hasArgument("--suppressDiagnosticEvents"),
                noGetErrOnBackgroundUpdate: server.hasArgument("--noGetErrOnBackgroundUpdate"),
                syntaxOnly: syntaxOnly,
                serverMode: serverMode
            }, logger, cancellationToken);
        }
        ts.setStackTraceLimit();
        // Cannot check process var directory in webworker so has to be typeof check here
        if (typeof process !== "undefined") {
            start(server.initializeNodeSystem(), require("os").platform());
        }
        else {
            // Get args from first message
            var listener_1 = function (e) {
                removeEventListener("message", listener_1);
                var args = e.data;
                start(server.initializeWebSystem(args), "web");
            };
            addEventListener("message", listener_1);
        }
    })(server = ts.server || (ts.server = {}));
})(ts || (ts = {}));
//# sourceMappingURL=tsserver.js.map